Version Description
rtMedia 4.5.7, with fixes for, media duplication in the lightbox, multiple media upload for non-admin roles, some UI fixes along with introduced new filters.
=
Download this release
Release Info
Developer | thrijith |
Plugin | rtMedia for WordPress, BuddyPress and bbPress |
Version | 4.5.7 |
Comparing to | |
See all releases |
Code changes from version 4.5.6 to 4.5.7
- app/admin/RTMediaAdmin.php +1 -1
- app/admin/RTMediaFormHandler.php +2 -2
- app/assets/admin/js/admin.min.js +1 -1
- app/assets/admin/js/settings.js +1 -0
- app/assets/css/rtmedia.css +19 -7
- app/assets/css/rtmedia.min.css +1 -1
- app/assets/css/sass/_media-tab.scss +4 -0
- app/assets/css/sass/_popup.scss +9 -10
- app/assets/css/sass/_rtm.scss +13 -3
- app/assets/js/rtMedia.backbone.js +28 -20
- app/assets/js/rtMedia.js +47 -0
- app/assets/js/rtmedia.min.js +2 -2
- app/helper/RTMediaSupport.php +3 -3
- app/main/controllers/activity/RTMediaActivity.php +127 -47
- app/main/controllers/activity/RTMediaBuddyPressActivity.php +11 -0
- app/main/controllers/media/RTMediaAlbum.php +1 -1
- app/main/controllers/media/RTMediaFeatured.php +1 -1
- app/main/controllers/media/RTMediaGalleryItemAction.php +3 -3
- app/main/controllers/media/RTMediaGroupFeatured.php +1 -1
- app/main/controllers/media/RTMediaLoginPopup.php +1 -1
- app/main/controllers/media/RTMediaMedia.php +2 -2
- app/main/controllers/media/RTMediaTags.php +11 -5
- app/main/controllers/media/RTMediaUserInteraction.php +2 -1
- app/main/controllers/template/rtmedia-actions.php +6 -6
- app/main/controllers/template/rtmedia-filters.php +5 -18
- app/main/controllers/template/rtmedia-functions.php +14 -8
- app/main/controllers/upload/RTMediaUploadView.php +4 -4
- index.php +2 -2
- languages/buddypress-media.po +3 -3
- lib/getid3/extension.cache.dbm.php +54 -12
- lib/getid3/extension.cache.mysql.php +50 -14
- lib/getid3/extension.cache.mysqli.php +220 -0
- lib/getid3/extension.cache.sqlite3.php +121 -84
- lib/getid3/getid3.lib.php +562 -121
- lib/getid3/getid3.php +1835 -1499
- lib/getid3/module.archive.gzip.php +40 -16
- lib/getid3/module.archive.rar.php +14 -9
- lib/getid3/module.archive.szip.php +11 -9
- lib/getid3/module.archive.tar.php +22 -8
- lib/getid3/module.archive.xz.php +42 -0
- lib/getid3/module.archive.zip.php +70 -36
- lib/getid3/module.audio-video.asf.php +106 -35
- lib/getid3/module.audio-video.bink.php +16 -9
- lib/getid3/module.audio-video.flv.php +187 -26
- lib/getid3/module.audio-video.matroska.php +132 -23
- lib/getid3/module.audio-video.mpeg.php +100 -27
- lib/getid3/module.audio-video.nsv.php +35 -18
- lib/getid3/module.audio-video.quicktime.php +1844 -1217
- lib/getid3/module.audio-video.real.php +24 -11
- lib/getid3/module.audio-video.riff.php +181 -48
- lib/getid3/module.audio-video.swf.php +10 -7
- lib/getid3/module.audio-video.ts.php +16 -10
- lib/getid3/module.audio.aa.php +13 -11
- lib/getid3/module.audio.aac.php +45 -20
- lib/getid3/module.audio.ac3.php +520 -176
- lib/getid3/module.audio.amr.php +19 -9
- lib/getid3/module.audio.au.php +25 -8
- lib/getid3/module.audio.avr.php +10 -8
- lib/getid3/module.audio.bonk.php +20 -8
- lib/getid3/module.audio.dsf.php +139 -0
- lib/getid3/module.audio.dss.php +42 -24
- lib/getid3/module.audio.dts.php +63 -20
- lib/getid3/module.audio.flac.php +85 -22
- lib/getid3/module.audio.la.php +18 -16
- lib/getid3/module.audio.lpac.php +16 -13
- lib/getid3/module.audio.midi.php +35 -17
- lib/getid3/module.audio.mod.php +29 -16
- lib/getid3/module.audio.monkey.php +24 -11
- lib/getid3/module.audio.mp3.php +200 -72
- lib/getid3/module.audio.mpc.php +57 -17
- lib/getid3/module.audio.ogg.php +120 -42
- lib/getid3/module.audio.optimfrog.php +54 -15
- lib/getid3/module.audio.rkau.php +16 -10
- lib/getid3/module.audio.shorten.php +16 -14
- lib/getid3/module.audio.tta.php +10 -8
- lib/getid3/module.audio.voc.php +25 -8
- lib/getid3/module.audio.vqf.php +24 -11
- lib/getid3/module.audio.wavpack.php +10 -8
app/admin/RTMediaAdmin.php
CHANGED
@@ -1840,7 +1840,7 @@ if ( ! class_exists( 'RTMediaAdmin' ) ) {
|
|
1840 |
// tab icon
|
1841 |
$icon = '';
|
1842 |
if ( isset( $tab['icon'] ) && ! empty( $tab['icon'] ) ) {
|
1843 |
-
$icon = '<i class="' . esc_attr( $tab['icon'] ) . ' dashicons
|
1844 |
}
|
1845 |
?>
|
1846 |
<li class="<?php echo esc_attr( $active_class ) ?> <?php echo esc_attr( $error_class ) ?>">
|
1840 |
// tab icon
|
1841 |
$icon = '';
|
1842 |
if ( isset( $tab['icon'] ) && ! empty( $tab['icon'] ) ) {
|
1843 |
+
$icon = '<i class="' . esc_attr( $tab['icon'] ) . ' dashicons"></i>';
|
1844 |
}
|
1845 |
?>
|
1846 |
<li class="<?php echo esc_attr( $active_class ) ?> <?php echo esc_attr( $error_class ) ?>">
|
app/admin/RTMediaFormHandler.php
CHANGED
@@ -881,7 +881,7 @@ class RTMediaFormHandler {
|
|
881 |
if ( 'other' !== $key ) {
|
882 |
?>
|
883 |
<span class="rtm-tooltip rtm-extensions">
|
884 |
-
<i class="dashicons dashicons-info
|
885 |
<span class="rtm-tip">
|
886 |
<strong><?php echo esc_html__( 'File Extensions', 'buddypress-media' ); ?></strong><br/>
|
887 |
<hr/>
|
@@ -1568,7 +1568,7 @@ class RTMediaFormHandler {
|
|
1568 |
<span
|
1569 |
class="rtm-field-wrap"><?php call_user_func( $option['callback'], $option['args'] ); ?></span>
|
1570 |
<span class="rtm-tooltip">
|
1571 |
-
<i class="dashicons dashicons-info
|
1572 |
<span class="rtm-tip">
|
1573 |
<?php echo wp_kses( ( isset( $option['args']['desc'] ) ) ? $option['args']['desc'] : 'NA', array(
|
1574 |
'a' => array(
|
881 |
if ( 'other' !== $key ) {
|
882 |
?>
|
883 |
<span class="rtm-tooltip rtm-extensions">
|
884 |
+
<i class="dashicons dashicons-info"></i>
|
885 |
<span class="rtm-tip">
|
886 |
<strong><?php echo esc_html__( 'File Extensions', 'buddypress-media' ); ?></strong><br/>
|
887 |
<hr/>
|
1568 |
<span
|
1569 |
class="rtm-field-wrap"><?php call_user_func( $option['callback'], $option['args'] ); ?></span>
|
1570 |
<span class="rtm-tooltip">
|
1571 |
+
<i class="dashicons dashicons-info"></i>
|
1572 |
<span class="rtm-tip">
|
1573 |
<?php echo wp_kses( ( isset( $option['args']['desc'] ) ) ? $option['args']['desc'] : 'NA', array(
|
1574 |
'a' => array(
|
app/assets/admin/js/admin.min.js
CHANGED
@@ -3,4 +3,4 @@
|
|
3 |
* @package rtMedia
|
4 |
*/
|
5 |
|
6 |
-
function rtmedia_addon_do_not_show(){var a={action:"rtmedia_addon_popup_not_show_again"};jQuery.post(rtmedia_admin_ajax,a,function(a){jQuery("#TB_window").remove(),jQuery("#TB_overlay").remove()})}"function"!=typeof Object.create&&(Object.create=function(a){function b(){}return b.prototype=a,new b}),function(a,b,c,d){var e={init:function(b,c){var d=this;d.elem=c,d.$elem=a(c),d.options=a.extend({},a.fn.rtTab.options,b),d.rtTabs()},rtTabs:function(){var c=this,d=c.options.activeTab;if(c.$elem.find("li:nth-child("+d+")").addClass("active"),c.rtTabContent(activeTabContent="yes"),c.rtClick(),!0==("false"!==c.$elem.attr("data-hash"))){var e=b.location.hash;e&&c.$elem.find("li").find('a[href="'+e+'"]').trigger("click"),a(b).on("hashchange",function(){var a=b.location.hash;c.$elem.find("li").find('a[href="'+a+'"]').trigger("click")})}},rtClick:function(){var c=this,d=c.$elem.find("li");d.find("a").on("click",function(e){e.preventDefault(),d.removeClass("active"),c.rtTabContent(),a(this).parent().addClass("active");var f=a(this).attr("href");if(a(f).removeClass("hide"),1==("false"!==c.$elem.attr("data-hash"))){var g=a(b).scrollTop();location.hash=a(this).attr("href"),a(b).scrollTop(g)}"function"==typeof c.options.onComplete&&c.options.onComplete.apply(c.elem,arguments)})},rtTabContent:function(b){this.$elem.find("li").find("a").each(function(){var c=a(this),d=c.attr("href");"yes"===b?c.parent().hasClass("active")||a(d).addClass("hide"):a(d).addClass("hide")})}};a.fn.rtTab=function(b){return this.each(function(){var c=Object.create(e);c.init(b,this),a.data(this,"rtTab",c)})},a.fn.rtTab.options={activeTab:1,onComplete:null}}(jQuery,window,document),jQuery(document).ready(function(a){var b=document.createElement("div");b.setAttribute("class","rtm-warning rtm-fly-warning hide"),a(".rtm-tabs").rtTab(),a('input[name^="rtmedia-options"]').on("change",function(){a(".rtm-save-settings-msg").remove(),0===a(".rtm-fly-warning").length&&(b.innerText=rtmedia_admin_strings.settings_changed,a(".rtm-button-container.top").prepend(b),a(".rtm-fly-warning").slideDown())}),a(".rtm-img-size-setting .form-table tr:nth-child(7) td:last-child").attr("colspan","3"),a(".rtm-field-wrap .switch input[type=checkbox]").each(function(){var b=a(this);b.parents("table").attr("data-depends")||(b.is(":checked")?(b.parents("table").next(".rtm-notice").slideDown(),b.parents("table").siblings("table").each(function(){a(this).attr("data-depends")&&a(this).slideDown()})):(b.parents("table").next(".rtm-notice").slideUp(),b.parents("table").siblings("table").each(function(){a(this).attr("data-depends")&&a(this).slideUp()}))),b.parents("tr").next("tr").attr("data-depends")&&(b.is(":checked")?b.parents("tr").next("tr").slideDown():b.parents("tr").next("tr").slideUp())}),a(".rtm-field-wrap .switch input[type=checkbox]").on("change",function(){var b=a(this);b.parents("table").attr("data-depends")||(b.parents("table").next(".rtm-notice").slideToggle(),b.parents("table").siblings("table").each(function(){a(this).attr("data-depends")&&a(this).slideToggle()})),b.parents("tr").next("tr").attr("data-depends")&&b.parents("tr").next("tr").slideToggle()});var c=Backbone.View.extend({el:a(".bp-media-admin"),events:{"click .rtm-theme":"render","click .rtm-close":"close","click .rtm-previous":"previousTheme","click .rtm-next":"nextTheme",keyup:"keyEvent"},initialize:function(){_.bindAll(this,"render","close","nextTheme","previousTheme","keyEvent"),this.keyEvent()},render:function(b){a(".rtm-theme").removeClass("rtm-modal-open");var c=a(b.currentTarget).addClass("rtm-modal-open").find(".rtm-theme-content").html();if(a(".rtm-theme-overlay")[0])a(".rtm-theme-overlay").show(),a(this.el).find(".rtm-theme-content-wrap").empty().append(c);else{var d={themeContent:c};a(this.el).append(rtMediaAdmin.templates.rtm_theme_overlay(d))}a(b.currentTarget).is(":first-child")?a(".rtm-previous").addClass("disabled"):a(b.currentTarget).is(":last-child")?a(".rtm-next").addClass("disabled"):a(".rtm-next, .rtm-previous").removeClass("disabled")},close:function(){a(".rtm-theme").removeClass("rtm-modal-open"),a(".rtm-theme-overlay").hide(),a(".rtm-next, .rtm-previous").removeClass("disabled")},nextTheme:function(b){return a(".rtm-next, .rtm-previous").removeClass("disabled"),a(".rtm-theme:last-child").hasClass("rtm-modal-open")&&a(b.currentTarget).addClass("disabled"),a(".rtm-modal-open").next().trigger("click"),!1},previousTheme:function(b){return a(".rtm-next, .rtm-previous").removeClass("disabled"),a(".rtm-theme:first-child").hasClass("rtm-modal-open")&&a(b.currentTarget).addClass("disabled"),a(".rtm-modal-open").prev().trigger("click"),!1},keyEvent:function(){a("body").on("keyup",function(b){return 39===b.keyCode?(a(".rtm-next, .rtm-previous").removeClass("disabled"),a(".rtm-theme:last-child").hasClass("rtm-modal-open")&&a(b.currentTarget).addClass("disabled"),a(".rtm-modal-open").next().trigger("click"),!1):37===b.keyCode?(a(".rtm-next, .rtm-previous").removeClass("disabled"),a(".rtm-theme:first-child").hasClass("rtm-modal-open")&&a(b.currentTarget).addClass("disabled"),a(".rtm-modal-open").prev().trigger("click"),!1):void(27===b.keyCode&&a(".rtm-close").trigger("click"))})}});new c;jQuery("#rtm-licenses .regular-text").each(function(){jQuery(this).keypress(function(a){if("13"==(a.keyCode?a.keyCode:a.which))return!1})}),jQuery("#bp_media_settings_form").on("submit",function(a){jQuery("#rtcss-notice").remove();var b=jQuery("#rtmedia-custom-css").val(),c=b.match(/@import\s*(url)?\s*\(?([^;]+?)\)?;/);if(null!=c){if(null!=c[0])return jQuery("#rtmedia-custom-css").after('<div id="rtcss-notice" class="error"><p>'+rtmedia_admin_strings.wrong_css_input+"</p></div>"),!1}})});var rtMediaAdmin=new Object;rtMediaAdmin.templates={rtm_image:wp.template("rtm-image"),rtm_msg_div:wp.template("rtm-msg-div"),rtm_album_favourites_importer:wp.template("rtm-album-favourites-importer"),rtm_map_mapping_failure:wp.template("rtm-map-mapping-failure"),rtm_p_tag:wp.template("rtm-p-tag"),rtm_theme_overlay:wp.template("rtm-theme-overlay")},jQuery(document).ready(function(a){function b(a){return jQuery.post(ajaxurl,a,function(b){if(0!=b){var c=!1,d=Math.ceil((20*parseInt(b)+parseInt(a.values.finished))/parseInt(a.values.total)*100);d>100&&(d=100,c=!0),jQuery("#rtprogressbar>div").css("width",d+"%"),finished=jQuery("#rtprivacyinstaller span.finished").html(),jQuery("#rtprivacyinstaller span.finished").html(parseInt(finished)+a.count),c&&jQuery.post(ajaxurl,{action:"rtmedia_privacy_redirect"},function(a){window.location=settings_url})}else{var e={msg:"Row "+b+" failed."};jQuery("#map_progress_msgs").html(rtMediaAdmin.templates.rtm_map_mapping_failure(e))}})}function c(a){return jQuery.getJSON(ajaxurl,a,function(b){if(favorites=!1,b){var c=Math.ceil((5*parseInt(b.page)+parseInt(a.values.finished))/parseInt(a.values.total)*100);comments_total=jQuery("#bpmedia-bpalbumimporter .bp-album-comments span.total").html(),users_total=jQuery("#bpmedia-bpalbumimporter .bp-album-users span.total").html(),media_total=jQuery("#bpmedia-bpalbumimporter .bp-album-media span.total").html(),comments_finished=jQuery("#bpmedia-bpalbumimporter .bp-album-comments span.finished").html(),users_finished=jQuery("#bpmedia-bpalbumimporter .bp-album-users span.finished").html();var f=Math.ceil((parseInt(b.comments)+parseInt(comments_finished))/parseInt(comments_total)*100),g=Math.ceil(parseInt(b.users)/parseInt(users_total)*100);(c>100||100==c)&&(c=100,favorites=!0),jQuery(".bp-album-media #rtprogressbar>div").css("width",c+"%"),jQuery(".bp-album-comments #rtprogressbar>div").css("width",f+"%"),jQuery(".bp-album-users #rtprogressbar>div").css("width",g+"%"),media_finished=jQuery("#bpmedia-bpalbumimporter .bp-album-media span.finished").html(),parseInt(media_finished)<parseInt(media_total)&&jQuery("#bpmedia-bpalbumimporter .bp-album-media span.finished").html(parseInt(media_finished)+a.count),jQuery("#bpmedia-bpalbumimporter .bp-album-comments span.finished").html(parseInt(b.comments)+parseInt(comments_finished)),jQuery("#bpmedia-bpalbumimporter .bp-album-users span.finished").html(parseInt(b.users)),favorites&&(favorite_data={action:"rtmedia_rt_album_import_favorites",rtm_wpnonce:jQuery("#bpaimporter_wpnonce").val()},jQuery.post(ajaxurl,favorite_data,function(a){if(!a.hasOwnProperty(favorites)||0===a.favorites&&"0"===a.favorites)window.setTimeout(e,2e3);else{if(!jQuery(".bp-album-favorites").length){var b={users:a.users};jQuery(".bp-album-comments").after(rtMediaAdmin.templates.rtm_album_favourites_importer(b))}$favorites={},0!=a.offset||"0"!=a.offset?start=1*a.offset+1:start=1;for(var c=start;c<=a.users;c++)$count=1,c==a.users&&($count=parseInt(a.users%$count),0==$count&&($count=1)),newvals={action:"rtmedia_rt_album_import_step_favorites",offset:1*(c-1),redirect:c==a.users,rtm_wpnonce:jQuery("#bpaimporter_wpnonce").val()},$favorites[c]=newvals;var f=jQuery.Deferred();f.resolve(),jQuery.each($favorites,function(a,b){f=f.pipe(function(){return d(b)})})}},"json"))}else if(a.hasOwnProperty(page)){var h={msg:"Row "+b.page+" failed."};jQuery("#map_progress_msgs").html(rtMediaAdmin.templates.rtm_map_mapping_failure(h))}else{var h={msg:rtmedia_admin_strings.request_failed};jQuery("#map_progress_msgs").html(rtMediaAdmin.templates.rtm_map_mapping_failure(h))}})}function d(a){return jQuery.post(ajaxurl,a,function(a){redirect=!1,favorites_total=jQuery("#bpmedia-bpalbumimporter .bp-album-favorites span.total").html(),favorites_finished=jQuery("#bpmedia-bpalbumimporter .bp-album-favorites span.finished").html(),jQuery("#bpmedia-bpalbumimporter .bp-album-favorites span.finished").html(parseInt(favorites_finished)+1);var b=Math.ceil(parseInt(favorites_finished+1)/parseInt(favorites_total)*100);(b>100||100==b)&&(b=100,redirect=!0),jQuery(".bp-album-favorites #rtprogressbar>div").css("width",b+"%"),redirect&&window.setTimeout(e,2e3)})}function e(){window.location=document.URL}function f(a){j=a.target.files,g(a)}function g(a){a.stopPropagation(),a.preventDefault();var b=new FormData;void 0!==a&&void 0!==a.target&&void 0!==a.target.name&&"rtFileInput"===a.target.name&&b.append("import_export_control",a.target.name),jQuery.each(j,function(a,c){b.append(a,c)});var c=jQuery("#rtmedia_admin_upload_nonce").val();void 0!==c&&""!==c&&b.append("rtmedia_admin_upload_nonce",c),b.append("action","rtmedia_admin_upload"),jQuery.ajax({url:rtmedia_admin_ajax,type:"POST",data:b,cache:!1,processData:!1,contentType:!1,success:function(a){if(a.hasOwnProperty("rtm_response")&&a.hasOwnProperty("rtm_response_msg")){jQuery("#rtm-setting-msg").remove();var b=jQuery("<div/>",{id:"rtm-setting-msg",class:"rtm-fly-warning"});"success"===a.rtm_response?(b.addClass("rtm-success rtm-save-settings-msg"),b.text(a.rtm_response_msg),jQuery(".rtm-button-container.top").append(b),location.reload()):"error"===a.rtm_response&&(b.addClass("rtm-warning"),b.text(a.rtm_response_msg),jQuery(".rtm-button-container.top").append(b),b.delay(3e3).fadeOut(100))}if(void 0===a.error){if(a.exceed_size_msg)return jQuery("#debuglog").val(""),alert(a.exceed_size_msg),!1;jQuery("#debuglog_temp_path").val(a.debug_attachmanet)}else jQuery("#debuglog").val(""),alert("ERRORS: "+a.error)}})}var h=a("#rtm-licenses");h.length>0&&h.find(".license-inner:first input:first").focus();var i=document.createElement("div");i.className="support_form_loader",a(".rtm-save-settings-msg").length>0&&setTimeout(function(){a(".rtm-save-settings-msg").remove()},1e4),jQuery("#spread-the-word").on("click","#bp-media-add-linkback",function(){var a={action:"rtmedia_linkback",linkback:jQuery("#bp-media-add-linkback:checked").length};jQuery.post(rtmedia_admin_ajax,a,function(a){})}),jQuery("#bp-media-settings-boxes").on("change","#select-request",function(){if(jQuery(this).val()){jQuery("#bp_media_settings_form .bp-media-metabox-holder").html(),jQuery("#bp_media_settings_form .bp-media-metabox-holder").html(i);var a={action:"rtmedia_select_request",form:jQuery(this).val()};jQuery.post(ajaxurl,a,function(a){jQuery("#bp_media_settings_form .bp-media-metabox-holder").html(),jQuery("#bp_media_settings_form .bp-media-metabox-holder").html(a).fadeIn("slow")})}}),jQuery("#bp-media-settings-boxes").on("click","#cancel-request",function(){if(jQuery(this).val()){jQuery("#bp_media_settings_form .bp-media-metabox-holder").html(),jQuery("#bp_media_settings_form .bp-media-metabox-holder").html(i);var a={action:"rtmedia_cancel_request"};jQuery.post(ajaxurl,a,function(a){jQuery("#bp_media_settings_form .bp-media-metabox-holder").html(),jQuery("#bp_media_settings_form .bp-media-metabox-holder").html(a).fadeIn("slow")})}}),jQuery("#bp-media-settings-boxes").on("submit","#bp_media_settings_form, .rtmedia-settings-submit",function(a){var b=!0,c=new RegExp("^[0-9]+$");jQuery("input[name*='defaultSizes']").each(function(a){if(!c.test(jQuery(this).val()))return alert("Invalid value for "+jQuery(this).attr("name").replace("rtmedia-options[defaultSizes_","").replace("]","").replace(/_/g," ").replace(/(\b)([a-zA-Z] )/g,function(a){return a.toUpperCase()})),b=!1,!1});var d=jQuery('input[name^="rtmedia-options[general_videothumbs]"]');if(b&&d.length>0&&void 0!==d){var e="",f=0;if(d.val()<=0?(e+=rtmedia_admin_strings.video_thumbnail_error,f=2):c.test(d.val())||(e+=rtmedia_admin_strings.video_thumbnail_invalid_value+" "+Math.round(d.val())+".",f=Math.round(d.val())),""!=e)return alert(e),d.val(f),b=!1,!1}var g=jQuery('input[name^="rtmedia-options[general_jpeg_image_quality]"]');if(b&&g.length>0&&void 0!==g){var e="",h=0;if(g.val()<=0?(e+=rtmedia_admin_strings.jpeg_quality_negative_error,h=90):g.val()>100?(e+=rtmedia_admin_strings.jpeg_quality_percentage_error,h=100):c.test(g.val())||(e+=rtmedia_admin_strings.jpeg_quality_invalid_value+" "+Math.round(g.val())+".",h=Math.round(g.val())),""!=e)return alert(e),g.val(h),b=!1,!1}var i=jQuery('input[name^="rtmedia-options[general_perPageMedia]"]');if(b&&i.length>0&&void 0!==i){var e="",j=0;if(i.val()<1?(e+=rtmedia_admin_strings.per_page_media_negative_value,j=10):jQuery.isNumeric(i.val())&&Math.floor(i.val())!=i.val()&&(e+=rtmedia_admin_strings.per_page_media_positive_error+" "+Math.round(i.val())+".",j=Math.round(i.val())),""!=e)return alert(e),i.val(j),b=!1,!1}b||a.preventDefault()}),jQuery(document).on("click","#bpm-services .encoding-try-now,#rtm-services .encoding-try-now",function(a){if(a.preventDefault(),confirm(rtmedia_admin_strings.are_you_sure)){var b={src:rtmedia_admin_url+"images/wpspin_light.gif"};jQuery(this).after(rtMediaAdmin.templates.rtm_image(b));var b={action:"rtmedia_free_encoding_subscribe"};jQuery.getJSON(ajaxurl,b,function(a){if(void 0===a.error&&a.apikey){var b=window.location.href,c=window.location.hash;b=b.replace(c,""),document.location.href=b+"&apikey="+a.apikey+c}else{jQuery(".encoding-try-now").next().remove(),jQuery("#settings-error-encoding-error").remove();var d={id:"settings-error-encoding-error",msg:a.error,class:"error"};jQuery("#bp-media-settings-boxes").before(rtMediaAdmin.templates.rtm_msg_div(d))}})}}),jQuery(document).on("click","#api-key-submit",function(a){if(a.preventDefault(),0==jQuery(this).next("img").length){var b={src:rtmedia_admin_url+"images/wpspin_light.gif"};jQuery(this).after(rtMediaAdmin.templates.rtm_image(b))}var b={action:"rtmedia_enter_api_key",apikey:jQuery("#new-api-key").val()};jQuery.getJSON(ajaxurl,b,function(a){if(void 0===a.error&&a.apikey){var b=window.location.href,c=window.location.hash;b=b.replace(c,""),-1==b.toString().indexOf("&apikey="+a.apikey)&&(b+="&apikey="+a.apikey),-1==b.toString().indexOf("&update=true")&&(b+="&update=true"),document.location.href=b+c}else{jQuery("#settings-error-api-key-error").remove();var d={id:"settings-error-api-key-error",msg:a.error,class:"error"};jQuery("h2:first").after(rtMediaAdmin.templates.rtm_msg_div(d))}jQuery("#api-key-submit").next("img").remove()})}),jQuery(document).on("click","#disable-encoding",function(a){if(a.preventDefault(),confirm(rtmedia_admin_strings.disable_encoding)){var b={src:rtmedia_admin_url+"images/wpspin_light.gif"};jQuery(this).after(rtMediaAdmin.templates.rtm_image(b));var b={action:"rtmedia_disable_encoding"};jQuery.post(ajaxurl,b,function(a){if(a){if(jQuery(".settings-error-encoding-disabled").remove(),jQuery("#settings-encoding-successfully-updated").length>0)jQuery("#settings-encoding-successfully-updated p").html(a);else{var b={id:"settings-encoding-successfully-updated",msg:a,class:"updated"};jQuery("h2:first").after(rtMediaAdmin.templates.rtm_msg_div(b))}jQuery("#rtmedia-encoding-usage").hide(),jQuery("#disable-encoding").next("img").remove(),jQuery("#disable-encoding").hide(),jQuery("#enable-encoding").show()}else{jQuery("#settings-error-encoding-disabled").remove();var b={id:"settings-error-encoding-disabled",msg:rtmedia_admin_strings.something_went_wrong,class:"error"};jQuery("h2:first").after(rtMediaAdmin.templates.rtm_msg_div(b))}})}}),jQuery(document).on("click","#enable-encoding",function(a){if(a.preventDefault(),confirm(rtmedia_admin_strings.enable_encoding)){var b={src:rtmedia_admin_url+"images/wpspin_light.gif"};jQuery(this).after(rtMediaAdmin.templates.rtm_image(b));var b={action:"rtmedia_enable_encoding"};jQuery.post(ajaxurl,b,function(a){if(a){if(jQuery(".settings-error-encoding-enabled").remove(),jQuery("#settings-encoding-successfully-updated").length>0)jQuery("#settings-encoding-successfully-updated p").html(a);else{var b={id:"settings-encoding-successfully-updated",msg:a,class:"updated"};jQuery("h2:first").after(rtMediaAdmin.templates.rtm_msg_div(b))}jQuery("#enable-encoding").next("img").remove(),jQuery("#enable-encoding").hide(),jQuery("#disable-encoding").show()}else{jQuery("#settings-error-encoding-disabled").remove();var b={id:"settings-error-encoding-enabled",msg:rtmedia_admin_strings.something_went_wrong,class:"error"};jQuery("h2:first").after(rtMediaAdmin.templates.rtm_msg_div(b))}})}}),jQuery(".bp-media-encoding-table").on("click",".bpm-unsubscribe",function(a){a.preventDefault(),jQuery("#bpm-unsubscribe-dialog").dialog({dialogClass:"wp-dialog",modal:!0,buttons:{Unsubscribe:function(){jQuery(this).dialog("close");var a={src:rtmedia_admin_url+"images/wpspin_light.gif"};jQuery(".bpm-unsubscribe").after(rtMediaAdmin.templates.rtm_image(a));var a={action:"rtmedia_unsubscribe_encoding_service",note:jQuery("#bpm-unsubscribe-note").val(),plan:jQuery(".bpm-unsubscribe").attr("data-plan"),price:jQuery(".bpm-unsubscribe").attr("data-price")};jQuery.getJSON(ajaxurl,a,function(a){if(void 0===a.error&&a.updated){jQuery(".bpm-unsubscribe").next().remove(),jQuery(".bpm-unsubscribe").after(a.form),jQuery(".bpm-unsubscribe").remove(),jQuery("#settings-unsubscribed-successfully").remove(),jQuery("#settings-unsubscribe-error").remove();var b={id:"settings-unsubscribed-successfully",msg:a.updated,class:"updated"};jQuery("h2:first").after(rtMediaAdmin.templates.rtm_msg_div(b)),window.location.hash="#settings-unsubscribed-successfully"}else{jQuery(".bpm-unsubscribe").next().remove(),jQuery("#settings-unsubscribed-successfully").remove(),jQuery("#settings-unsubscribe-error").remove();var b={id:"settings-unsubscribe-error",msg:a.error,class:"error"};jQuery("h2:first").after(rtMediaAdmin.templates.rtm_msg_div(b)),window.location.hash="#settings-unsubscribe-error"}})}}})}),jQuery("#bpmedia-bpalbumimporter").on("change","#bp-album-import-accept",function(){jQuery(".bp-album-import-accept").toggleClass("i-accept"),jQuery(".bp-album-importer-wizard").slideToggle()}),jQuery("#rtprivacyinstall").click(function(a){a.preventDefault(),$progress_parent=jQuery("#rtprivacyinstaller"),$progress_parent.find(".rtprivacytype").each(function(){if($type=jQuery(this).attr("id"),"total"==$type){$values=[],jQuery(this).find("input").each(function(){$values[jQuery(this).attr("name")]=[jQuery(this).val()]}),$data={};for(var a=1;a<=$values.steps[0];a++)$count=20,a==$values.steps[0]&&($count=parseInt($values.laststep[0]),0==$count&&($count=20)),newvals={page:a,action:"rtmedia_privacy_install",count:$count,values:$values},$data[a]=newvals;var c=jQuery.Deferred();c.resolve(),jQuery.each($data,function(a,d){c=c.pipe(function(){return b(d)})})}})}),jQuery("#bpmedia-bpalbumimport-cleanup").click(function(a){a.preventDefault(),jQuery.post(ajaxurl,{action:"rtmedia_rt_album_cleanup",rtm_wpnonce:jQuery("#bpaimporter_wpnonce").val()},function(a){window.location=settings_rt_album_import_url})}),jQuery("#bpmedia-bpalbumimporter").on("click","#bpmedia-bpalbumimport",function(a){if(a.preventDefault(),!jQuery("#bp-album-import-accept").prop("checked")){jQuery("html, body").animate({scrollTop:jQuery("#bp-album-import-accept").offset().top},500);var b=jQuery(".bp-album-import-accept"),d=3;return void function a(){b.css("background-color","#EE0000"),setTimeout(function(){b.css("background-color","#FFEBE8"),--d&&setTimeout(a,500)},500)}()}if(jQuery(this).prop("disabled",!0),wp_admin_url=ajaxurl.replace("admin-ajax.php",""),!jQuery(".bpm-ajax-loader").length){var e={src:rtmedia_admin_url+"images/wpspin_light.gif",class:"bpm-ajax-loader",norefresh:rtmedia_admin_strings.no_refresh};jQuery(this).after(rtMediaAdmin.templates.rtm_image(e))}$progress_parent=jQuery("#bpmedia-bpalbumimport"),$values=[],jQuery(this).parent().find("input").each(function(){$values[jQuery(this).attr("name")]=[jQuery(this).val()]}),0==$values.steps[0]&&($values.steps[0]=1),$data={};for(var d=1;d<=$values.steps[0];d++)$count=5,d==$values.steps[0]&&($count=parseInt($values.laststep[0]),0==$count&&($count=5)),newvals={page:d,action:"rtmedia_rt_album_import",count:$count,values:$values,rtm_wpnonce:jQuery("#bpaimporter_wpnonce").val()},$data[d]=newvals;var f=jQuery.Deferred();f.resolve(),jQuery.each($data,function(a,b){f=f.pipe(function(){return c(b)})})}),jQuery("#bp-media-settings-boxes").on("click",".interested",function(){jQuery(".interested-container").removeClass("hidden"),jQuery(".choice-free").attr("required","required")}),jQuery("#bp-media-settings-boxes").on("click",".not-interested",function(){jQuery(".interested-container").addClass("hidden"),jQuery(".choice-free").removeAttr("required")}),jQuery("#video-transcoding-main-container").on("click",".video-transcoding-survey",function(a){a.preventDefault();var b={action:"rtmedia_convert_videos_form",email:jQuery(".email").val(),url:jQuery(".url").val(),choice:jQuery('input[name="choice"]:checked').val(),interested:jQuery('input[name="interested"]:checked').val()};return jQuery.post(ajaxurl,b,function(a){var b={msg:a,strong:"yes"};jQuery("#video-transcoding-main-container").html(rtMediaAdmin.templates.rtm_p_tag(b))}),!1}),jQuery("#bpmedia-bpalbumimporter").on("click",".deactivate-bp-album",function(a){a.preventDefault(),$bpalbum=jQuery(this);var b={action:"rtmedia_rt_album_deactivate",rtm_wpnonce:jQuery("#bpaimporter_wpnonce").val()};jQuery.get(ajaxurl,b,function(a){if(a)location.reload();else{var b={msg:rtmedia_admin_strings.something_went_wrong};$bpalbum.parent().after(rtMediaAdmin.templates.rtm_p_tag(b))}})}),jQuery(".updated").on("click",".bpm-hide-encoding-notice",function(){var a={src:rtmedia_admin_url+"images/wpspin_light.gif"};jQuery(this).after(rtMediaAdmin.templates.rtm_image(a));var a={action:"rtmedia_hide_encoding_notice"};jQuery.post(ajaxurl,a,function(a){a&&jQuery(".bpm-hide-encoding-notice").closest(".updated").remove()})}),jQuery("#rtmedia-bp-enable-activity").is(":checked")?jQuery(".rtmedia-bp-activity-setting").prop("readonly",!1):jQuery(".rtmedia-bp-activity-setting").prop("readonly",!0),jQuery("#rtmedia-bp-enable-activity").on("click",function(a){jQuery(this).is(":checked")?jQuery(".rtmedia-bp-activity-setting").prop("readonly",!1):jQuery(".rtmedia-bp-activity-setting").prop("readonly",!0)});void 0!==rtmedia_on_label&&rtmedia_on_label,void 0!==rtmedia_off_label&&rtmedia_off_label;var j;jQuery("input[type=file]").on("change",f),jQuery("#rtmedia-submit-request").click(function(){var b=jQuery("#name").val(),c=jQuery("#email").val(),d=jQuery("#website").val(),e=jQuery("#subject").val(),f=jQuery("#details").val(),g=jQuery('input[name="request_type"]').val(),h=jQuery('input[name="request_id"]').val(),i=jQuery('input[name="server_address"]').val(),j=jQuery('input[name="ip_address"]').val(),k=jQuery('input[name="server_type"]').val(),l=jQuery('input[name="user_agent"]').val(),m=jQuery('input[name="debuglog_temp_path"]').val(),n={name:b,email:c,website:d,subject:e,details:f,request_id:h,request_type:"premium_support",server_address:i,ip_address:j,server_type:k,user_agent:l,debuglog_temp_path:m};if("bug_report"==g){var o=jQuery("#wp_admin_username").val();if(""==o)return alert(rtmedia_admin_support_strings.wp_admin_username_error),!1;var p=jQuery("#wp_admin_pwd").val();if(""==p)return alert(rtmedia_admin_support_strings.wp_admin_pwd_error),!1;var q=jQuery("#ssh_ftp_host").val();if(""==q)return alert(rtmedia_admin_support_strings.ssh_ftp_host_error),!1;var r=jQuery("#ssh_ftp_username").val();if(""==r)return alert(rtmedia_admin_support_strings.ssh_ftp_username_error),!1;var s=jQuery("#ssh_ftp_pwd").val();if(""==s)return alert(rtmedia_admin_support_strings.ssh_ftp_pwd_error),!1;n={name:b,email:c,website:d,subject:e,details:f,request_id:h,request_type:"premium_support",server_address:i,ip_address:j,server_type:k,user_agent:l,wp_admin_username:o,wp_admin_pwd:p,ssh_ftp_host:q,ssh_ftp_username:r,ssh_ftp_pwd:s}}for(formdata in n){if(""==n[formdata]&&"debuglog_temp_path"!=formdata)return alert("Please enter "+formdata.replace("_"," ")+" field."),!1;if(""==n[formdata]&&"debuglog_temp_path"==formdata)return alert("Please upload attachment."),!1}return data={action:"rtmedia_submit_request",form_data:n,support_wpnonce:jQuery("#support_wpnonce").val()},jQuery.post(ajaxurl,data,function(b){if("false"==(b=b.trim()))return alert(rtmedia_admin_support_strings.all_fields_error),!1;a("#rtmedia_service_contact_container").empty(),a("#rtmedia_service_contact_container").append(b)}),!1}),jQuery("#cancel-request").click(function(){return!1}),jQuery(".rtm_enable_masonry_view input[type=checkbox]").is(":checked")?jQuery(".rtm_enable_masonry_view").parents(".metabox-holder").find(".rtmedia-info").show():jQuery(".rtm_enable_masonry_view").parents(".metabox-holder").find(".rtmedia-info").hide(),jQuery(".rtm_enable_masonry_view input[type=checkbox]").on("click",function(a){jQuery(this).is(":checked")?jQuery(".rtm_enable_masonry_view").parents(".metabox-holder").find(".rtmedia-info").show():jQuery(".rtm_enable_masonry_view").parents(".metabox-holder").find(".rtmedia-info").hide()}),jQuery("#rtm-masonry-change-thumbnail-info").click(function(a){jQuery("html, body").animate({scrollTop:0},"500","swing")}),jQuery("#rtm-export-button").click(function(){data={action:"rtmedia_export_settings"},jQuery.post(ajaxurl,data,function(a){var b="data:text/json;charset=utf-8,"+encodeURIComponent(JSON.stringify(a)),c=document.createElement("a");c.setAttribute("href",b),c.setAttribute("download","rtm-settings.json"),c.click(),c.remove()})}),jQuery("#rtm-export-data-button").click(function(){window.location.href="/wp-admin/tools.php?page=export_personal_data"}),jQuery("#rtm-erase-data-button").click(function(){window.location.href="/wp-admin/tools.php?page=remove_personal_data"})}),jQuery(window).load(function(){jQuery(".rtmedia-addon-thickbox").trigger("click")});
|
3 |
* @package rtMedia
|
4 |
*/
|
5 |
|
6 |
+
function rtmedia_addon_do_not_show(){var a={action:"rtmedia_addon_popup_not_show_again"};jQuery.post(rtmedia_admin_ajax,a,function(a){jQuery("#TB_window").remove(),jQuery("#TB_overlay").remove()})}"function"!=typeof Object.create&&(Object.create=function(a){function b(){}return b.prototype=a,new b}),function(a,b,c,d){var e={init:function(b,c){var d=this;d.elem=c,d.$elem=a(c),d.options=a.extend({},a.fn.rtTab.options,b),d.rtTabs()},rtTabs:function(){var c=this,d=c.options.activeTab;if(c.$elem.find("li:nth-child("+d+")").addClass("active"),c.rtTabContent(activeTabContent="yes"),c.rtClick(),!0==("false"!==c.$elem.attr("data-hash"))){var e=b.location.hash;e&&c.$elem.find("li").find('a[href="'+e+'"]').trigger("click"),a(b).on("hashchange",function(){var a=b.location.hash;c.$elem.find("li").find('a[href="'+a+'"]').trigger("click")})}},rtClick:function(){var c=this,d=c.$elem.find("li");d.find("a").on("click",function(e){e.preventDefault(),d.removeClass("active"),c.rtTabContent(),a(this).parent().addClass("active");var f=a(this).attr("href");if(a(f).removeClass("hide"),1==("false"!==c.$elem.attr("data-hash"))){var g=a(b).scrollTop();location.hash=a(this).attr("href"),a(b).scrollTop(g)}"function"==typeof c.options.onComplete&&c.options.onComplete.apply(c.elem,arguments)})},rtTabContent:function(b){this.$elem.find("li").find("a").each(function(){var c=a(this),d=c.attr("href");"yes"===b?c.parent().hasClass("active")||a(d).addClass("hide"):a(d).addClass("hide")})}};a.fn.rtTab=function(b){return this.each(function(){var c=Object.create(e);c.init(b,this),a.data(this,"rtTab",c)})},a.fn.rtTab.options={activeTab:1,onComplete:null}}(jQuery,window,document),jQuery(document).ready(function(a){var b=document.createElement("div");b.setAttribute("class","rtm-warning rtm-fly-warning hide"),a(".rtm-tabs").rtTab(),a('input[name^="rtmedia-options"]').on("change",function(){a(".rtm-save-settings-msg").remove(),0===a(".rtm-fly-warning").length&&(b.innerText=rtmedia_admin_strings.settings_changed,a(".rtm-button-container.top").prepend(b),a(".rtm-fly-warning").slideDown())}),a(".rtm-img-size-setting .form-table tr:nth-child(7) td:last-child").attr("colspan","3"),a(".rtm-field-wrap .switch input[type=checkbox]").each(function(){var b=a(this);b.parents("table").attr("data-depends")||(b.is(":checked")?(b.parents("table").next(".rtm-notice").slideDown(),b.parents("table").siblings("table").each(function(){a(this).attr("data-depends")&&a(this).slideDown()})):(b.parents("table").next(".rtm-notice").slideUp(),b.parents("table").siblings("table").each(function(){a(this).attr("data-depends")&&a(this).slideUp()}))),b.parents("tr").next("tr").attr("data-depends")&&(b.is(":checked")?b.parents("tr").next("tr").slideDown():b.parents("tr").next("tr").slideUp())}),a(".rtm-field-wrap .switch input[type=checkbox]").on("change",function(){var b=a(this);b.parents("table").attr("data-depends")||(b.parents("table").next(".rtm-notice").slideToggle(),b.parents("table").siblings("table").each(function(){a(this).attr("data-depends")&&a(this).slideToggle()})),b.parents("tr").next("tr").attr("data-depends")&&b.parents("tr").next("tr").slideToggle()});var c=Backbone.View.extend({el:a(".bp-media-admin"),events:{"click .rtm-theme":"render","click .rtm-close":"close","click .rtm-previous":"previousTheme","click .rtm-next":"nextTheme",keyup:"keyEvent"},initialize:function(){_.bindAll(this,"render","close","nextTheme","previousTheme","keyEvent"),this.keyEvent()},render:function(b){a(".rtm-theme").removeClass("rtm-modal-open");var c=a(b.currentTarget).addClass("rtm-modal-open").find(".rtm-theme-content").html();if(a(".rtm-theme-overlay")[0])a(".rtm-theme-overlay").show(),a(this.el).find(".rtm-theme-content-wrap").empty().append(c);else{var d={themeContent:c};a(this.el).append(rtMediaAdmin.templates.rtm_theme_overlay(d))}a(b.currentTarget).is(":first-child")?a(".rtm-previous").addClass("disabled"):a(b.currentTarget).is(":last-child")?a(".rtm-next").addClass("disabled"):a(".rtm-next, .rtm-previous").removeClass("disabled")},close:function(){a(".rtm-theme").removeClass("rtm-modal-open"),a(".rtm-theme-overlay").hide(),a(".rtm-next, .rtm-previous").removeClass("disabled")},nextTheme:function(b){return a(".rtm-next, .rtm-previous").removeClass("disabled"),a(".rtm-theme:last-child").hasClass("rtm-modal-open")&&a(b.currentTarget).addClass("disabled"),a(".rtm-modal-open").next().trigger("click"),!1},previousTheme:function(b){return a(".rtm-next, .rtm-previous").removeClass("disabled"),a(".rtm-theme:first-child").hasClass("rtm-modal-open")&&a(b.currentTarget).addClass("disabled"),a(".rtm-modal-open").prev().trigger("click"),!1},keyEvent:function(){a("body").on("keyup",function(b){return 39===b.keyCode?(a(".rtm-next, .rtm-previous").removeClass("disabled"),a(".rtm-theme:last-child").hasClass("rtm-modal-open")&&a(b.currentTarget).addClass("disabled"),a(".rtm-modal-open").next().trigger("click"),!1):37===b.keyCode?(a(".rtm-next, .rtm-previous").removeClass("disabled"),a(".rtm-theme:first-child").hasClass("rtm-modal-open")&&a(b.currentTarget).addClass("disabled"),a(".rtm-modal-open").prev().trigger("click"),!1):void(27===b.keyCode&&a(".rtm-close").trigger("click"))})}});new c;jQuery("#rtm-licenses .regular-text").each(function(){jQuery(this).keypress(function(a){if("13"==(a.keyCode?a.keyCode:a.which))return!1})}),jQuery("#bp_media_settings_form").on("submit",function(a){jQuery("#rtcss-notice").remove();var b=jQuery("#rtmedia-custom-css").val(),c=b.match(/@import\s*(url)?\s*\(?([^;]+?)\)?;/);if(null!=c){if(null!=c[0])return jQuery("#rtmedia-custom-css").after('<div id="rtcss-notice" class="error"><p>'+rtmedia_admin_strings.wrong_css_input+"</p></div>"),!1}})});var rtMediaAdmin=new Object;rtMediaAdmin.templates={rtm_image:wp.template("rtm-image"),rtm_msg_div:wp.template("rtm-msg-div"),rtm_album_favourites_importer:wp.template("rtm-album-favourites-importer"),rtm_map_mapping_failure:wp.template("rtm-map-mapping-failure"),rtm_p_tag:wp.template("rtm-p-tag"),rtm_theme_overlay:wp.template("rtm-theme-overlay")},jQuery(document).ready(function(a){function b(a){return jQuery.post(ajaxurl,a,function(b){if(0!=b){var c=!1,d=Math.ceil((20*parseInt(b)+parseInt(a.values.finished))/parseInt(a.values.total)*100);d>100&&(d=100,c=!0),jQuery("#rtprogressbar>div").css("width",d+"%"),finished=jQuery("#rtprivacyinstaller span.finished").html(),jQuery("#rtprivacyinstaller span.finished").html(parseInt(finished)+a.count),c&&jQuery.post(ajaxurl,{action:"rtmedia_privacy_redirect"},function(a){window.location=settings_url})}else{var e={msg:"Row "+b+" failed."};jQuery("#map_progress_msgs").html(rtMediaAdmin.templates.rtm_map_mapping_failure(e))}})}function c(a){return jQuery.getJSON(ajaxurl,a,function(b){if(favorites=!1,b){var c=Math.ceil((5*parseInt(b.page)+parseInt(a.values.finished))/parseInt(a.values.total)*100);comments_total=jQuery("#bpmedia-bpalbumimporter .bp-album-comments span.total").html(),users_total=jQuery("#bpmedia-bpalbumimporter .bp-album-users span.total").html(),media_total=jQuery("#bpmedia-bpalbumimporter .bp-album-media span.total").html(),comments_finished=jQuery("#bpmedia-bpalbumimporter .bp-album-comments span.finished").html(),users_finished=jQuery("#bpmedia-bpalbumimporter .bp-album-users span.finished").html();var f=Math.ceil((parseInt(b.comments)+parseInt(comments_finished))/parseInt(comments_total)*100),g=Math.ceil(parseInt(b.users)/parseInt(users_total)*100);(c>100||100==c)&&(c=100,favorites=!0),jQuery(".bp-album-media #rtprogressbar>div").css("width",c+"%"),jQuery(".bp-album-comments #rtprogressbar>div").css("width",f+"%"),jQuery(".bp-album-users #rtprogressbar>div").css("width",g+"%"),media_finished=jQuery("#bpmedia-bpalbumimporter .bp-album-media span.finished").html(),parseInt(media_finished)<parseInt(media_total)&&jQuery("#bpmedia-bpalbumimporter .bp-album-media span.finished").html(parseInt(media_finished)+a.count),jQuery("#bpmedia-bpalbumimporter .bp-album-comments span.finished").html(parseInt(b.comments)+parseInt(comments_finished)),jQuery("#bpmedia-bpalbumimporter .bp-album-users span.finished").html(parseInt(b.users)),favorites&&(favorite_data={action:"rtmedia_rt_album_import_favorites",rtm_wpnonce:jQuery("#bpaimporter_wpnonce").val()},jQuery.post(ajaxurl,favorite_data,function(a){if(!a.hasOwnProperty(favorites)||0===a.favorites&&"0"===a.favorites)window.setTimeout(e,2e3);else{if(!jQuery(".bp-album-favorites").length){var b={users:a.users};jQuery(".bp-album-comments").after(rtMediaAdmin.templates.rtm_album_favourites_importer(b))}$favorites={},0!=a.offset||"0"!=a.offset?start=1*a.offset+1:start=1;for(var c=start;c<=a.users;c++)$count=1,c==a.users&&($count=parseInt(a.users%$count),0==$count&&($count=1)),newvals={action:"rtmedia_rt_album_import_step_favorites",offset:1*(c-1),redirect:c==a.users,rtm_wpnonce:jQuery("#bpaimporter_wpnonce").val()},$favorites[c]=newvals;var f=jQuery.Deferred();f.resolve(),jQuery.each($favorites,function(a,b){f=f.pipe(function(){return d(b)})})}},"json"))}else if(a.hasOwnProperty(page)){var h={msg:"Row "+b.page+" failed."};jQuery("#map_progress_msgs").html(rtMediaAdmin.templates.rtm_map_mapping_failure(h))}else{var h={msg:rtmedia_admin_strings.request_failed};jQuery("#map_progress_msgs").html(rtMediaAdmin.templates.rtm_map_mapping_failure(h))}})}function d(a){return jQuery.post(ajaxurl,a,function(a){redirect=!1,favorites_total=jQuery("#bpmedia-bpalbumimporter .bp-album-favorites span.total").html(),favorites_finished=jQuery("#bpmedia-bpalbumimporter .bp-album-favorites span.finished").html(),jQuery("#bpmedia-bpalbumimporter .bp-album-favorites span.finished").html(parseInt(favorites_finished)+1);var b=Math.ceil(parseInt(favorites_finished+1)/parseInt(favorites_total)*100);(b>100||100==b)&&(b=100,redirect=!0),jQuery(".bp-album-favorites #rtprogressbar>div").css("width",b+"%"),redirect&&window.setTimeout(e,2e3)})}function e(){window.location=document.URL}function f(a){j=a.target.files,g(a)}function g(a){a.stopPropagation(),a.preventDefault();var b=new FormData;void 0!==a&&void 0!==a.target&&void 0!==a.target.name&&"rtFileInput"===a.target.name&&b.append("import_export_control",a.target.name),jQuery.each(j,function(a,c){b.append(a,c)});var c=jQuery("#rtmedia_admin_upload_nonce").val();void 0!==c&&""!==c&&b.append("rtmedia_admin_upload_nonce",c),b.append("action","rtmedia_admin_upload"),jQuery.ajax({url:rtmedia_admin_ajax,type:"POST",data:b,cache:!1,processData:!1,contentType:!1,success:function(a){if(a.hasOwnProperty("rtm_response")&&a.hasOwnProperty("rtm_response_msg")){jQuery("#rtm-setting-msg").remove();var b=jQuery("<div/>",{id:"rtm-setting-msg",class:"rtm-fly-warning"});"success"===a.rtm_response?(b.addClass("rtm-success rtm-save-settings-msg"),b.text(a.rtm_response_msg),jQuery(".rtm-button-container.top").append(b),location.reload()):"error"===a.rtm_response&&(b.addClass("rtm-warning"),b.text(a.rtm_response_msg),jQuery(".rtm-button-container.top").append(b),b.delay(3e3).fadeOut(100))}if(void 0===a.error){if(a.exceed_size_msg)return jQuery("#debuglog").val(""),alert(a.exceed_size_msg),!1;jQuery("#debuglog_temp_path").val(a.debug_attachmanet)}else jQuery("#debuglog").val(""),alert("ERRORS: "+a.error)}})}var h=a("#rtm-licenses");h.length>0&&h.find(".license-inner:first input:first").focus();var i=document.createElement("div");i.className="support_form_loader",a(".rtm-save-settings-msg").length>0&&setTimeout(function(){a(".rtm-save-settings-msg").remove()},1e4),jQuery("#spread-the-word").on("click","#bp-media-add-linkback",function(){var a={action:"rtmedia_linkback",linkback:jQuery("#bp-media-add-linkback:checked").length};jQuery.post(rtmedia_admin_ajax,a,function(a){})}),jQuery("#bp-media-settings-boxes").on("change","#select-request",function(){if(jQuery(this).val()){jQuery("#bp_media_settings_form .bp-media-metabox-holder").html(),jQuery("#bp_media_settings_form .bp-media-metabox-holder").html(i);var a={action:"rtmedia_select_request",form:jQuery(this).val()};jQuery.post(ajaxurl,a,function(a){jQuery("#bp_media_settings_form .bp-media-metabox-holder").html(),jQuery("#bp_media_settings_form .bp-media-metabox-holder").html(a).fadeIn("slow")})}}),jQuery("#bp-media-settings-boxes").on("click","#cancel-request",function(){if(jQuery(this).val()){jQuery("#bp_media_settings_form .bp-media-metabox-holder").html(),jQuery("#bp_media_settings_form .bp-media-metabox-holder").html(i);var a={action:"rtmedia_cancel_request"};jQuery.post(ajaxurl,a,function(a){jQuery("#bp_media_settings_form .bp-media-metabox-holder").html(),jQuery("#bp_media_settings_form .bp-media-metabox-holder").html(a).fadeIn("slow")})}}),jQuery("#bp-media-settings-boxes").on("submit","#bp_media_settings_form, .rtmedia-settings-submit",function(a){var b=!0,c=new RegExp("^[0-9]+$");jQuery("input[name*='defaultSizes']").each(function(a){if(!c.test(jQuery(this).val()))return alert("Invalid value for "+jQuery(this).attr("name").replace("rtmedia-options[defaultSizes_","").replace("]","").replace(/_/g," ").replace(/(\b)([a-zA-Z] )/g,function(a){return a.toUpperCase()})),b=!1,!1});var d=jQuery('input[name^="rtmedia-options[general_videothumbs]"]');if(b&&d.length>0&&void 0!==d){var e="",f=0;if(d.val()<=0?(e+=rtmedia_admin_strings.video_thumbnail_error,f=2):c.test(d.val())||(e+=rtmedia_admin_strings.video_thumbnail_invalid_value+" "+Math.round(d.val())+".",f=Math.round(d.val())),""!=e)return alert(e),d.val(f),b=!1,!1}var g=jQuery('input[name^="rtmedia-options[general_jpeg_image_quality]"]');if(b&&g.length>0&&void 0!==g){var e="",h=0;if(g.val()<=0?(e+=rtmedia_admin_strings.jpeg_quality_negative_error,h=90):g.val()>100?(e+=rtmedia_admin_strings.jpeg_quality_percentage_error,h=100):c.test(g.val())||(e+=rtmedia_admin_strings.jpeg_quality_invalid_value+" "+Math.round(g.val())+".",h=Math.round(g.val())),""!=e)return alert(e),g.val(h),b=!1,!1}var i=jQuery('input[name^="rtmedia-options[general_perPageMedia]"]');if(b&&i.length>0&&void 0!==i){var e="",j=0;if(i.val()<1?(e+=rtmedia_admin_strings.per_page_media_negative_value,j=10):jQuery.isNumeric(i.val())&&Math.floor(i.val())!=i.val()&&(e+=rtmedia_admin_strings.per_page_media_positive_error+" "+Math.round(i.val())+".",j=Math.round(i.val())),""!=e)return alert(e),i.val(j),b=!1,!1}b||a.preventDefault()}),jQuery(document).on("click","#bpm-services .encoding-try-now,#rtm-services .encoding-try-now",function(a){if(a.preventDefault(),confirm(rtmedia_admin_strings.are_you_sure)){var b={src:rtmedia_admin_url+"images/wpspin_light.gif"};jQuery(this).after(rtMediaAdmin.templates.rtm_image(b));var b={action:"rtmedia_free_encoding_subscribe"};jQuery.getJSON(ajaxurl,b,function(a){if(void 0===a.error&&a.apikey){var b=window.location.href,c=window.location.hash;b=b.replace(c,""),document.location.href=b+"&apikey="+a.apikey+c}else{jQuery(".encoding-try-now").next().remove(),jQuery("#settings-error-encoding-error").remove();var d={id:"settings-error-encoding-error",msg:a.error,class:"error"};jQuery("#bp-media-settings-boxes").before(rtMediaAdmin.templates.rtm_msg_div(d))}})}}),jQuery(document).on("click","#api-key-submit",function(a){if(a.preventDefault(),0==jQuery(this).next("img").length){var b={src:rtmedia_admin_url+"images/wpspin_light.gif"};jQuery(this).after(rtMediaAdmin.templates.rtm_image(b))}var b={action:"rtmedia_enter_api_key",apikey:jQuery("#new-api-key").val()};jQuery.getJSON(ajaxurl,b,function(a){if(void 0===a.error&&a.apikey){var b=window.location.href,c=window.location.hash;b=b.replace(c,""),-1==b.toString().indexOf("&apikey="+a.apikey)&&(b+="&apikey="+a.apikey),-1==b.toString().indexOf("&update=true")&&(b+="&update=true"),document.location.href=b+c}else{jQuery("#settings-error-api-key-error").remove();var d={id:"settings-error-api-key-error",msg:a.error,class:"error"};jQuery("h2:first").after(rtMediaAdmin.templates.rtm_msg_div(d))}jQuery("#api-key-submit").next("img").remove()})}),jQuery(document).on("click","#disable-encoding",function(a){if(a.preventDefault(),confirm(rtmedia_admin_strings.disable_encoding)){var b={src:rtmedia_admin_url+"images/wpspin_light.gif"};jQuery(this).after(rtMediaAdmin.templates.rtm_image(b));var b={action:"rtmedia_disable_encoding"};jQuery.post(ajaxurl,b,function(a){if(a){if(jQuery(".settings-error-encoding-disabled").remove(),jQuery("#settings-encoding-successfully-updated").length>0)jQuery("#settings-encoding-successfully-updated p").html(a);else{var b={id:"settings-encoding-successfully-updated",msg:a,class:"updated"};jQuery("h2:first").after(rtMediaAdmin.templates.rtm_msg_div(b))}jQuery("#rtmedia-encoding-usage").hide(),jQuery("#disable-encoding").next("img").remove(),jQuery("#disable-encoding").hide(),jQuery("#enable-encoding").show()}else{jQuery("#settings-error-encoding-disabled").remove();var b={id:"settings-error-encoding-disabled",msg:rtmedia_admin_strings.something_went_wrong,class:"error"};jQuery("h2:first").after(rtMediaAdmin.templates.rtm_msg_div(b))}})}}),jQuery(document).on("click","#enable-encoding",function(a){if(a.preventDefault(),confirm(rtmedia_admin_strings.enable_encoding)){var b={src:rtmedia_admin_url+"images/wpspin_light.gif"};jQuery(this).after(rtMediaAdmin.templates.rtm_image(b));var b={action:"rtmedia_enable_encoding"};jQuery.post(ajaxurl,b,function(a){if(a){if(jQuery(".settings-error-encoding-enabled").remove(),jQuery("#settings-encoding-successfully-updated").length>0)jQuery("#settings-encoding-successfully-updated p").html(a);else{var b={id:"settings-encoding-successfully-updated",msg:a,class:"updated"};jQuery("h2:first").after(rtMediaAdmin.templates.rtm_msg_div(b))}jQuery("#enable-encoding").next("img").remove(),jQuery("#enable-encoding").hide(),jQuery("#disable-encoding").show()}else{jQuery("#settings-error-encoding-disabled").remove();var b={id:"settings-error-encoding-enabled",msg:rtmedia_admin_strings.something_went_wrong,class:"error"};jQuery("h2:first").after(rtMediaAdmin.templates.rtm_msg_div(b))}})}}),jQuery(".bp-media-encoding-table").on("click",".bpm-unsubscribe",function(a){a.preventDefault(),jQuery("#bpm-unsubscribe-dialog").dialog({dialogClass:"wp-dialog",modal:!0,buttons:{Unsubscribe:function(){jQuery(this).dialog("close");var a={src:rtmedia_admin_url+"images/wpspin_light.gif"};jQuery(".bpm-unsubscribe").after(rtMediaAdmin.templates.rtm_image(a));var a={action:"rtmedia_unsubscribe_encoding_service",note:jQuery("#bpm-unsubscribe-note").val(),plan:jQuery(".bpm-unsubscribe").attr("data-plan"),price:jQuery(".bpm-unsubscribe").attr("data-price")};jQuery.getJSON(ajaxurl,a,function(a){if(void 0===a.error&&a.updated){jQuery(".bpm-unsubscribe").next().remove(),jQuery(".bpm-unsubscribe").after(a.form),jQuery(".bpm-unsubscribe").remove(),jQuery("#settings-unsubscribed-successfully").remove(),jQuery("#settings-unsubscribe-error").remove();var b={id:"settings-unsubscribed-successfully",msg:a.updated,class:"updated"};jQuery("h2:first").after(rtMediaAdmin.templates.rtm_msg_div(b)),window.location.hash="#settings-unsubscribed-successfully"}else{jQuery(".bpm-unsubscribe").next().remove(),jQuery("#settings-unsubscribed-successfully").remove(),jQuery("#settings-unsubscribe-error").remove();var b={id:"settings-unsubscribe-error",msg:a.error,class:"error"};jQuery("h2:first").after(rtMediaAdmin.templates.rtm_msg_div(b)),window.location.hash="#settings-unsubscribe-error"}})}}})}),jQuery("#bpmedia-bpalbumimporter").on("change","#bp-album-import-accept",function(){jQuery(".bp-album-import-accept").toggleClass("i-accept"),jQuery(".bp-album-importer-wizard").slideToggle()}),jQuery("#rtprivacyinstall").click(function(a){a.preventDefault(),$progress_parent=jQuery("#rtprivacyinstaller"),$progress_parent.find(".rtprivacytype").each(function(){if($type=jQuery(this).attr("id"),"total"==$type){$values=[],jQuery(this).find("input").each(function(){$values[jQuery(this).attr("name")]=[jQuery(this).val()]}),$data={};for(var a=1;a<=$values.steps[0];a++)$count=20,a==$values.steps[0]&&($count=parseInt($values.laststep[0]),0==$count&&($count=20)),newvals={page:a,action:"rtmedia_privacy_install",count:$count,values:$values},$data[a]=newvals;var c=jQuery.Deferred();c.resolve(),jQuery.each($data,function(a,d){c=c.pipe(function(){return b(d)})})}})}),jQuery("#bpmedia-bpalbumimport-cleanup").click(function(a){a.preventDefault(),jQuery.post(ajaxurl,{action:"rtmedia_rt_album_cleanup",rtm_wpnonce:jQuery("#bpaimporter_wpnonce").val()},function(a){window.location=settings_rt_album_import_url})}),jQuery("#bpmedia-bpalbumimporter").on("click","#bpmedia-bpalbumimport",function(a){if(a.preventDefault(),!jQuery("#bp-album-import-accept").prop("checked")){jQuery("html, body").animate({scrollTop:jQuery("#bp-album-import-accept").offset().top},500);var b=jQuery(".bp-album-import-accept"),d=3;return void function a(){b.css("background-color","#EE0000"),setTimeout(function(){b.css("background-color","#FFEBE8"),--d&&setTimeout(a,500)},500)}()}if(jQuery(this).prop("disabled",!0),wp_admin_url=ajaxurl.replace("admin-ajax.php",""),!jQuery(".bpm-ajax-loader").length){var e={src:rtmedia_admin_url+"images/wpspin_light.gif",class:"bpm-ajax-loader",norefresh:rtmedia_admin_strings.no_refresh};jQuery(this).after(rtMediaAdmin.templates.rtm_image(e))}$progress_parent=jQuery("#bpmedia-bpalbumimport"),$values=[],jQuery(this).parent().find("input").each(function(){$values[jQuery(this).attr("name")]=[jQuery(this).val()]}),0==$values.steps[0]&&($values.steps[0]=1),$data={};for(var d=1;d<=$values.steps[0];d++)$count=5,d==$values.steps[0]&&($count=parseInt($values.laststep[0]),0==$count&&($count=5)),newvals={page:d,action:"rtmedia_rt_album_import",count:$count,values:$values,rtm_wpnonce:jQuery("#bpaimporter_wpnonce").val()},$data[d]=newvals;var f=jQuery.Deferred();f.resolve(),jQuery.each($data,function(a,b){f=f.pipe(function(){return c(b)})})}),jQuery("#bp-media-settings-boxes").on("click",".interested",function(){jQuery(".interested-container").removeClass("hidden"),jQuery(".choice-free").attr("required","required")}),jQuery("#bp-media-settings-boxes").on("click",".not-interested",function(){jQuery(".interested-container").addClass("hidden"),jQuery(".choice-free").removeAttr("required")}),jQuery("#video-transcoding-main-container").on("click",".video-transcoding-survey",function(a){a.preventDefault();var b={action:"rtmedia_convert_videos_form",email:jQuery(".email").val(),url:jQuery(".url").val(),choice:jQuery('input[name="choice"]:checked').val(),interested:jQuery('input[name="interested"]:checked').val()};return jQuery.post(ajaxurl,b,function(a){var b={msg:a,strong:"yes"};jQuery("#video-transcoding-main-container").html(rtMediaAdmin.templates.rtm_p_tag(b))}),!1}),jQuery("#bpmedia-bpalbumimporter").on("click",".deactivate-bp-album",function(a){a.preventDefault(),$bpalbum=jQuery(this);var b={action:"rtmedia_rt_album_deactivate",rtm_wpnonce:jQuery("#bpaimporter_wpnonce").val()};jQuery.get(ajaxurl,b,function(a){if(a)location.reload();else{var b={msg:rtmedia_admin_strings.something_went_wrong};$bpalbum.parent().after(rtMediaAdmin.templates.rtm_p_tag(b))}})}),jQuery(".updated").on("click",".bpm-hide-encoding-notice",function(){var a={src:rtmedia_admin_url+"images/wpspin_light.gif"};jQuery(this).after(rtMediaAdmin.templates.rtm_image(a));var a={action:"rtmedia_hide_encoding_notice"};jQuery.post(ajaxurl,a,function(a){a&&jQuery(".bpm-hide-encoding-notice").closest(".updated").remove()})}),jQuery("#rtmedia-bp-enable-activity").is(":checked")?jQuery(".rtmedia-bp-activity-setting").prop("readonly",!1):jQuery(".rtmedia-bp-activity-setting").prop("readonly",!0),jQuery("#rtmedia-bp-enable-activity").on("click",function(a){jQuery(this).is(":checked")?jQuery(".rtmedia-bp-activity-setting").prop("readonly",!1):jQuery(".rtmedia-bp-activity-setting").prop("readonly",!0)});void 0!==rtmedia_on_label&&rtmedia_on_label,void 0!==rtmedia_off_label&&rtmedia_off_label;var j;jQuery("input[type=file]").on("change",f),jQuery("#rtmedia-submit-request").click(function(){var b=jQuery("#name").val(),c=jQuery("#email").val(),d=jQuery("#website").val(),e=jQuery("#subject").val(),f=jQuery("#details").val(),g=jQuery('input[name="request_type"]').val(),h=jQuery('input[name="request_id"]').val(),i=jQuery('input[name="server_address"]').val(),j=jQuery('input[name="ip_address"]').val(),k=jQuery('input[name="server_type"]').val(),l=jQuery('input[name="user_agent"]').val(),m=jQuery('input[name="debuglog_temp_path"]').val(),n={name:b,email:c,website:d,subject:e,details:f,request_id:h,request_type:"premium_support",server_address:i,ip_address:j,server_type:k,user_agent:l,debuglog_temp_path:m};if("bug_report"==g){var o=jQuery("#wp_admin_username").val();if(""==o)return alert(rtmedia_admin_support_strings.wp_admin_username_error),!1;var p=jQuery("#wp_admin_pwd").val();if(""==p)return alert(rtmedia_admin_support_strings.wp_admin_pwd_error),!1;var q=jQuery("#ssh_ftp_host").val();if(""==q)return alert(rtmedia_admin_support_strings.ssh_ftp_host_error),!1;var r=jQuery("#ssh_ftp_username").val();if(""==r)return alert(rtmedia_admin_support_strings.ssh_ftp_username_error),!1;var s=jQuery("#ssh_ftp_pwd").val();if(""==s)return alert(rtmedia_admin_support_strings.ssh_ftp_pwd_error),!1;n={name:b,email:c,website:d,subject:e,details:f,request_id:h,request_type:"premium_support",server_address:i,ip_address:j,server_type:k,user_agent:l,wp_admin_username:o,wp_admin_pwd:p,ssh_ftp_host:q,ssh_ftp_username:r,ssh_ftp_pwd:s}}for(formdata in n){if(""==n[formdata]&&"debuglog_temp_path"!=formdata)return alert("Please enter "+formdata.replace("_"," ")+" field."),!1;if(""==n[formdata]&&"debuglog_temp_path"==formdata)return alert("Please upload attachment."),!1}return data={action:"rtmedia_submit_request",form_data:n,support_wpnonce:jQuery("#support_wpnonce").val()},jQuery.post(ajaxurl,data,function(b){if("false"==(b=b.trim()))return alert(rtmedia_admin_support_strings.all_fields_error),!1;a("#rtmedia_service_contact_container").empty(),a("#rtmedia_service_contact_container").append(b)}),!1}),jQuery("#cancel-request").click(function(){return!1}),jQuery(".rtm_enable_masonry_view input[type=checkbox]").is(":checked")?jQuery(".rtm_enable_masonry_view").parents(".metabox-holder").find(".rtmedia-info").show():jQuery(".rtm_enable_masonry_view").parents(".metabox-holder").find(".rtmedia-info").hide(),jQuery(".rtm_enable_masonry_view input[type=checkbox]").on("click",function(a){jQuery(this).is(":checked")?jQuery(".rtm_enable_masonry_view").parents(".metabox-holder").find(".rtmedia-info").show():jQuery(".rtm_enable_masonry_view").parents(".metabox-holder").find(".rtmedia-info").hide()}),jQuery("#rtm-masonry-change-thumbnail-info").click(function(a){jQuery("html, body").animate({scrollTop:0},"500","swing")}),jQuery("#rtm-export-button").click(function(){data={action:"rtmedia_export_settings"},jQuery.post(ajaxurl,data,function(a){var b="data:text/json;charset=utf-8,"+encodeURIComponent(JSON.stringify(a)),c=document.createElement("a");c.setAttribute("href",b),c.setAttribute("download","rtm-settings.json"),jQuery("body").append(c),c.click(),c.remove()})}),jQuery("#rtm-export-data-button").click(function(){window.location.href="/wp-admin/tools.php?page=export_personal_data"}),jQuery("#rtm-erase-data-button").click(function(){window.location.href="/wp-admin/tools.php?page=remove_personal_data"})}),jQuery(window).load(function(){jQuery(".rtmedia-addon-thickbox").trigger("click")});
|
app/assets/admin/js/settings.js
CHANGED
@@ -965,6 +965,7 @@ jQuery( document ).ready( function ( $ ) {
|
|
965 |
var downloadAnchorNode = document.createElement( 'a' );
|
966 |
downloadAnchorNode.setAttribute( 'href', dataStr );
|
967 |
downloadAnchorNode.setAttribute( 'download', 'rtm-settings.json' );
|
|
|
968 |
downloadAnchorNode.click();
|
969 |
downloadAnchorNode.remove();
|
970 |
} );
|
965 |
var downloadAnchorNode = document.createElement( 'a' );
|
966 |
downloadAnchorNode.setAttribute( 'href', dataStr );
|
967 |
downloadAnchorNode.setAttribute( 'download', 'rtm-settings.json' );
|
968 |
+
jQuery( 'body' ).append( downloadAnchorNode );
|
969 |
downloadAnchorNode.click();
|
970 |
downloadAnchorNode.remove();
|
971 |
} );
|
app/assets/css/rtmedia.css
CHANGED
@@ -343,6 +343,9 @@ button#rtmedia-add-media-button-post-update .dashicons {
|
|
343 |
#buddypress a.rtm-button-back {
|
344 |
padding: 3px 10px;
|
345 |
}
|
|
|
|
|
|
|
346 |
|
347 |
.rtmedia_next_prev {
|
348 |
padding: 0 10px;
|
@@ -359,6 +362,10 @@ button#rtmedia-add-media-button-post-update .dashicons {
|
|
359 |
.rtm-page-number .rtmedia-page-link {
|
360 |
float: left;
|
361 |
}
|
|
|
|
|
|
|
|
|
362 |
|
363 |
.rtm-pagination {
|
364 |
background: transparent;
|
@@ -398,7 +405,7 @@ button#rtmedia-add-media-button-post-update .dashicons {
|
|
398 |
#rtmedia_go_to_num {
|
399 |
font-size: 16px;
|
400 |
margin: 0 5px;
|
401 |
-
padding:
|
402 |
width: 80px;
|
403 |
}
|
404 |
|
@@ -1160,7 +1167,7 @@ img.mfp-img {
|
|
1160 |
/*
|
1161 |
* popup autocomplete
|
1162 |
*/
|
1163 |
-
|
1164 |
z-index: 2147483647;
|
1165 |
}
|
1166 |
|
@@ -1260,10 +1267,6 @@ img.mfp-img {
|
|
1260 |
padding: 0 4px 0 0;
|
1261 |
}
|
1262 |
|
1263 |
-
#buddypress #rtm-media-options-list .rtm-options form button {
|
1264 |
-
font-size: small;
|
1265 |
-
}
|
1266 |
-
|
1267 |
#buddypress #rtm-media-options-list .rtm-options .button {
|
1268 |
background: transparent;
|
1269 |
border: 0 none;
|
@@ -1274,13 +1277,18 @@ img.mfp-img {
|
|
1274 |
font-weight: normal;
|
1275 |
line-height: 24px;
|
1276 |
padding: 0 6px;
|
1277 |
-
text-shadow: 0 0 0;
|
1278 |
text-transform: none;
|
1279 |
}
|
1280 |
#buddypress #rtm-media-options-list .rtm-options .rtmedia-delete-favlist {
|
1281 |
color: #FFFFFF;
|
1282 |
padding: 0;
|
1283 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1284 |
|
1285 |
.rtm-options.rtm-options {
|
1286 |
background: #666666;
|
@@ -2596,6 +2604,10 @@ body div.bp_members.bp_member .entry-content {
|
|
2596 |
display: none;
|
2597 |
}
|
2598 |
|
|
|
|
|
|
|
|
|
2599 |
.rtmedia-uploader .drag-drop {
|
2600 |
border: 4px dashed #DDD;
|
2601 |
text-align: center;
|
343 |
#buddypress a.rtm-button-back {
|
344 |
padding: 3px 10px;
|
345 |
}
|
346 |
+
#buddypress div.rtmedia-page-no.rtm-page-number a.rtmedia-page-link.button {
|
347 |
+
padding: 5px 10px;
|
348 |
+
}
|
349 |
|
350 |
.rtmedia_next_prev {
|
351 |
padding: 0 10px;
|
362 |
.rtm-page-number .rtmedia-page-link {
|
363 |
float: left;
|
364 |
}
|
365 |
+
.rtm-page-number .rtm-go-to-num,
|
366 |
+
.rtm-page-number .rtmedia-page-link {
|
367 |
+
line-height: 1.5;
|
368 |
+
}
|
369 |
|
370 |
.rtm-pagination {
|
371 |
background: transparent;
|
405 |
#rtmedia_go_to_num {
|
406 |
font-size: 16px;
|
407 |
margin: 0 5px;
|
408 |
+
padding: 3px 5px;
|
409 |
width: 80px;
|
410 |
}
|
411 |
|
1167 |
/*
|
1168 |
* popup autocomplete
|
1169 |
*/
|
1170 |
+
.atwho-container #atwho-ground-comment_content .atwho-view {
|
1171 |
z-index: 2147483647;
|
1172 |
}
|
1173 |
|
1267 |
padding: 0 4px 0 0;
|
1268 |
}
|
1269 |
|
|
|
|
|
|
|
|
|
1270 |
#buddypress #rtm-media-options-list .rtm-options .button {
|
1271 |
background: transparent;
|
1272 |
border: 0 none;
|
1277 |
font-weight: normal;
|
1278 |
line-height: 24px;
|
1279 |
padding: 0 6px;
|
|
|
1280 |
text-transform: none;
|
1281 |
}
|
1282 |
#buddypress #rtm-media-options-list .rtm-options .rtmedia-delete-favlist {
|
1283 |
color: #FFFFFF;
|
1284 |
padding: 0;
|
1285 |
}
|
1286 |
+
#buddypress #rtm-media-options-list .rtm-options form button {
|
1287 |
+
font-size: 14px;
|
1288 |
+
}
|
1289 |
+
#buddypress #rtm-media-options-list .rtm-options i {
|
1290 |
+
line-height: 1.7;
|
1291 |
+
}
|
1292 |
|
1293 |
.rtm-options.rtm-options {
|
1294 |
background: #666666;
|
2604 |
display: none;
|
2605 |
}
|
2606 |
|
2607 |
+
h2.rtm-gallery-title {
|
2608 |
+
margin: 10px 0;
|
2609 |
+
}
|
2610 |
+
|
2611 |
.rtmedia-uploader .drag-drop {
|
2612 |
border: 4px dashed #DDD;
|
2613 |
text-align: center;
|
app/assets/css/rtmedia.min.css
CHANGED
@@ -1 +1 @@
|
|
1 |
-
.alignleft{float:left}.alignright{float:right}.aligncenter{display:block;margin-left:auto;margin-right:auto;text-align:center}.clear-both{clear:both}.clear-none{clear:none}.clear-left{clear:left}.clear-right{clear:right}.rtm-inline-block{display:inline-block}.rtm-text-left{text-align:left}.rtm-text-right{text-align:right}.rtm-text-center{text-align:center}.rtm-border-0{border:0 !important}.hide{display:none}.rtmedia-success,.rtmedia-warning{margin:10px 0;padding:8px 14px 8px 14px;text-shadow:0 1px 0 rgba(255,255,255,0.5);border-bottom:1px solid #e7e7e7;cursor:pointer}.rtmedia-success{background-color:#dff0d8;color:#468847}.rtmedia-warning{background-color:#F0D8DD;color:#884646}.clearfix:after{content:"";display:table;clear:both}#buddypress form#whats-new-form textarea{box-sizing:border-box;min-height:70px;width:100%}#buddypress #whats-new-form .rtmedia-uploader-div{display:none}#buddypress #whats-new-form #whats-new-options .rtmedia-uploader-div{display:block}#buddypress #whats-new-options{height:auto !important;overflow:hidden}#buddypress form#whats-new-form p.activity-greeting{line-height:1}#buddypress form#whats-new-form #whats-new-options select{border:1px solid #ccc;font-size:13px;margin-top:0;padding:3px 2px}#whats-new-submit #aw-whats-new-submit{font-size:12px;line-height:18px;padding:4px 6px}#whats-new-post-in-box{float:left;font-size:13px}#buddypress form#whats-new-form #whats-new-submit{margin-top:0}#whats-new-textarea{margin-bottom:10px}body.media.buddypress{overflow-y:auto}#buddypress input[type=submit]:focus{background:#ededed;border:1px solid #bbb;color:#555;outline:0;text-decoration:none}#buddypress ul.activity-list li.activity-item .activity-comments .rtmedia-uploader-div{color:#767676;margin-left:50px;padding-left:15px}#buddypress form#whats-new-form #whats-new-content.active #whats-new-options[style] #whats-new-post-in-box{margin-top:0}#whats-new-post-in-box{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.rtmedia-container{box-sizing:border-box}.rtmedia-container *,.rtmedia-container *:before,.rtmedia-container *:after{box-sizing:inherit}.rtmedia-list.rtmedia-list{list-style:none;margin:0;padding:0}.rtmedia-list-item>a{border:0;display:inline-block;text-decoration:none}.rtmedia-list-item>a:focus{outline:0}.rtmedia-list-item>a+p{display:none}.rtmedia-list-item>a .rtmedia-item-thumbnail{width:150px;text-align:center}.rtmedia-list-item>a .rtmedia-item-thumbnail img{display:inline-block;max-height:inherit}#rtmedia-uploader-form .rtm-plupload-list,form .rtmedia-container .rtm-plupload-list,#rtmedia_uploader_filelist{list-style:none;margin-left:-4px;margin-right:-4px;padding-left:0;padding-top:10px}#rtmedia-uploader-form .rtm-plupload-list li,form .rtmedia-container .rtm-plupload-list li,#rtmedia_uploader_filelist li{background:#eee;float:left;margin:4px;max-width:110px;padding:5px;z-index:1;position:relative}#rtmedia-uploader-form .rtm-plupload-list li.upload-error,form .rtmedia-container .rtm-plupload-list li.upload-error,#rtmedia_uploader_filelist li.upload-error{border:1px solid red}#rtmedia-uploader-form .rtm-plupload-list img,form .rtmedia-container .rtm-plupload-list img,#rtmedia_uploader_filelist img{max-width:100%}#rtmedia-uploader-form .rtm-plupload-list canvas,form .rtmedia-container .rtm-plupload-list canvas,#rtmedia_uploader_filelist canvas{display:block;max-width:100%}#rtmedia-uploader-form .rtm-plupload-list .rtm-upload-edit-title,form .rtmedia-container .rtm-plupload-list .rtm-upload-edit-title,#rtmedia_uploader_filelist .rtm-upload-edit-title{font-size:12px}#rtmedia-uploader-form .rtm-plupload-list .rtm-upload-edit-desc,form .rtmedia-container .rtm-plupload-list .rtm-upload-edit-desc,#rtmedia_uploader_filelist .rtm-upload-edit-desc{font-size:12px;display:block}#rtmedia-uploader-form .rtm-plupload-list .rtm-upload-edit-title-wrapper label,#rtmedia-uploader-form .rtm-plupload-list .rtm-upload-edit-desc-wrapper label,form .rtmedia-container .rtm-plupload-list .rtm-upload-edit-title-wrapper label,form .rtmedia-container .rtm-plupload-list .rtm-upload-edit-desc-wrapper label,#rtmedia_uploader_filelist .rtm-upload-edit-title-wrapper label,#rtmedia_uploader_filelist .rtm-upload-edit-desc-wrapper label{display:block}#rtmedia-uploader-form .rtm-plupload-list .rtm-upload-edit-title-wrapper input.rtm-upload-edit-title,#rtmedia-uploader-form .rtm-plupload-list .rtm-upload-edit-desc-wrapper input.rtm-upload-edit-title,form .rtmedia-container .rtm-plupload-list .rtm-upload-edit-title-wrapper input.rtm-upload-edit-title,form .rtmedia-container .rtm-plupload-list .rtm-upload-edit-desc-wrapper input.rtm-upload-edit-title,#rtmedia_uploader_filelist .rtm-upload-edit-title-wrapper input.rtm-upload-edit-title,#rtmedia_uploader_filelist .rtm-upload-edit-desc-wrapper input.rtm-upload-edit-title{min-width:100%;margin-top:1px}.rtm-plupload-list:empty{display:none}.rtmedia-uploader-div,.rtmedia-uploader{clear:both}.rtm-upload-button-wrapper button.rtmedia-comment-media-upload,button.rtmedia-comment-media-upload{padding:3px 6px}.rtm-upload-button-wrapper button.rtmedia-comment-media-upload .dashicons,button.rtmedia-comment-media-upload .dashicons{font-size:18px;line-height:20px}button#rtmedia-add-media-button-post-update{padding:3px 6px}button#rtmedia-add-media-button-post-update .dashicons{font-size:18px;line-height:20px}.plupload_file_name{font-size:11px;font-weight:bold;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.plupload_file_size{color:#666;font-size:10px}.plupload_file_action{background:#eee;position:absolute;height:18px;right:4px;top:0;width:18px;z-index:10}.plupload_file_action .dashicons{color:#DD3D36;cursor:pointer;font-size:16px;height:18px;padding:2px 1px;width:18px}.plupload_file_status{height:15px;margin-bottom:5px;overflow:hidden}.plupload_file_progress{background:#7AD03A;height:100%;font-size:10px;line-height:15px;text-align:center;word-wrap:initial}.rtm-form .rtm-field-wrap{margin-bottom:20px}#buddypress a.rtm-button-back{padding:3px 10px}.rtmedia_next_prev{padding:0 10px}.rtm-page-number{float:left}.rtm-page-number .rtm-label{line-height:30px}.rtm-page-number .rtm-label,.rtm-page-number .rtm-go-to-num,.rtm-page-number .rtmedia-page-link{float:left}.rtm-pagination{background:transparent;border:none;color:#888;font-size:small;margin:0;position:relative;display:block;float:left;width:100%;padding:10px 0}.rtm-pagination .rtm-paginate{float:right;font-size:15px}.rtm-pagination .rtm-paginate a,.rtm-pagination .rtm-paginate span{display:inline-block;line-height:1;margin:0 2px;padding:8px;text-decoration:none}.rtm-pagination .rtm-paginate a.rtmedia-page-link{padding:8px}.rtm-pagination .dashicons{font-size:14px;height:auto;line-height:1.2;margin:0;padding:0;width:auto}#rtmedia_go_to_num{font-size:16px;margin:0 5px;padding:4px 5px;width:80px}.rtmedia-upload-not-allowed{background-color:#fcf8e3;border-bottom:1px solid #EEE;color:#c09853;margin-bottom:20px;padding:10px 15px}.plupload_file_name{position:relative}.plupload_file_name .dashicons{background:#eee;color:#DD3D36;cursor:pointer;font-size:14px;height:auto;padding:0 2px 0 5px;position:absolute;right:0;top:0;width:auto}.plupload_file_name .dashicons-yes{color:#7AD03A}.rtmedia-gallery-item-actions{background-color:rgba(0,0,0,0.6);opacity:0;position:absolute;text-align:center;-webkit-transition:all ease-in-out 0.4s;transition:all ease-in-out 0.4s;width:100%;z-index:9}.rtmedia-gallery-item-actions a{border:0;box-shadow:0 0 0;color:#fff;display:inline-block;font-size:12px;outline:none;padding:4px;text-align:left;text-decoration:none;text-transform:uppercase}.rtmedia-gallery-item-actions .dashicons{font-size:17px;margin-right:2px;position:relative;top:1px}.rtmedia-gallery-item-actions .dashicons-trash{font-size:15px}.rtm-pro-allow-action .rtmedia-list-item:hover .rtmedia-gallery-item-actions{opacity:1}.rtm-pro-allow-action .rtmedia-list-item:hover .rtmedia-bulk-edit-item-wrap+.rtmedia-gallery-item-actions{opacity:0}.rtmedia-footer-link{clear:both;overflow:hidden;padding:16px 0;position:relative;text-align:center}.rtmedia-text-link-decoration,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-edit a,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-edit span,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-delete a,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-delete span,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-title a,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-title span{text-decoration:none}.rtmedia-text-link-decoration:hover,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-edit a:hover,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-edit span:hover,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-delete a:hover,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-delete span:hover,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-title a:hover,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-title span:hover{text-decoration:underline}.rtmedia-container .rtmedia-edit-list-media-table{max-height:300px;overflow-y:auto}.rtmedia-container .rtmedia-edit-list-media-table thead tr{background-color:#50A1D7}.rtmedia-container .rtmedia-edit-list-media-table thead th{text-align:center;color:#FFF}.rtmedia-container .rtmedia-edit-list-media-table tbody tr:nth-child(odd){background:#FFF}.rtmedia-container .rtmedia-edit-list-media-table tbody tr:nth-child(even){background:#DCDCDC}table.rtmedia-edit-media-list tr{line-height:30px}table.rtmedia-edit-media-list tr th{color:#333;padding:4px 10px;line-height:20px}table.rtmedia-edit-media-list tr .rtm-edit-media-list-heading{width:44%}table.rtmedia-edit-media-list tr .rtm-edit-media-list-title-heading{width:56%}table.rtmedia-edit-media-list tr td.rtm-edit-media-list-edit,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-delete,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-title{padding:4px;font-size:14px;line-height:24px}table.rtmedia-edit-media-list tr td.rtm-edit-media-list-title a{text-decoration:none;color:#333}table.rtmedia-edit-media-list tr td.rtm-edit-media-list-edit{text-align:center}table.rtmedia-edit-media-list tr td.rtm-edit-media-list-edit a{color:#333;font-size:13px}table.rtmedia-edit-media-list tr td.rtm-edit-media-list-delete{text-align:center}table.rtmedia-edit-media-list tr td.rtm-edit-media-list-delete span{color:#FF0000;cursor:pointer;font-size:13px}.rtm-hide{display:none}.rtmedia-list-item .rtmedia-album-media-count{position:absolute;top:0;right:0;background-color:black;color:white;padding:0 5px}.rtmedia-actions-before-description>div{margin-bottom:5px}input.imgedit-submit-btn{display:none}.rtmedia-no-media-found,.rtmedia-list-media{min-height:95px}.privacy_message_wrapper{background:rgba(0,0,0,0.95);z-index:999;color:#fff;display:block;position:fixed;width:100%;padding:5px}.privacy_message_wrapper p{margin:20px 25px;width:-webkit-calc( 100% - 100px );width:calc( 100% - 100px );max-width:100%;font-size:85%;text-align:justify;word-wrap:break-word;display:inline-block}.privacy_message_wrapper p a{color:#fff;text-decoration:underline}.privacy_message_wrapper p a:hover{color:#000}.privacy_message_wrapper #close_rtm_privacy_message{margin:0px;float:right;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);position:absolute;display:inline-block;color:inherit;font-size:25px}.privacy_message_wrapper #close_rtm_privacy_message:hover{cursor:pointer}.hide_privacy_wrapper{display:none}.rtm-tabs.rtm-tabs{border-bottom:1px solid #eee;list-style:none;margin:0 0 20px;padding:0}.rtm-tabs li{border:1px solid #eee;border-bottom:0;float:left;margin:0 5px;padding:0}.rtm-tabs a{border:0;display:block;padding:5px 15px;text-decoration:none}.rtm-tabs a:focus{background:transparent;box-shadow:0 0 0}.rtm-tabs .active{position:relative}.rtm-tabs .active:after{background:#fff;bottom:-1px;content:' ';height:1px;left:0;position:absolute;width:100%}.rtm-tabs .dashicons{font-size:16px;height:auto;line-height:20px;margin-right:8px;width:auto}.rtmedia-edit-media-tabs .rtm-tabs a{border-bottom:0 none}.mfp-bg{top:0;left:0;width:100%;height:100%;z-index:104211;overflow:hidden;position:fixed;background:rgba(0,0,0,0.9)}.mfp-wrap{top:0;left:0;width:100%;height:100%;z-index:104311;position:fixed;outline:none !important;-webkit-backface-visibility:hidden}.mfp-container{text-align:center;position:absolute;width:100%;max-width:84%;margin:0 auto;right:0;height:100%;left:0;top:0;padding:0 8px;box-sizing:border-box}.mfp-container:before{content:' ';display:inline-block;height:100%;vertical-align:middle}.mfp-align-top .mfp-container:before{display:none}.mfp-content{position:relative;display:inline-block;vertical-align:middle;margin:0 auto;text-align:left;z-index:1045}.mfp-inline-holder .mfp-content,.mfp-ajax-holder .mfp-content{width:100%;cursor:auto}.mfp-ajax-cur{cursor:progress}.mfp-zoom-out-cur,.mfp-zoom-out-cur .mfp-image-holder .mfp-close{cursor:zoom-out}.mfp-zoom{cursor:pointer;cursor:zoom-in}.mfp-auto-cursor .mfp-content{cursor:auto}.mfp-close,.mfp-arrow,.mfp-preloader,.mfp-counter{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.mfp-loading.mfp-figure{display:none}.mfp-hide{display:none !important}.mfp-s-ready .mfp-preloader{display:none}.mfp-s-error .mfp-content{display:none}button.mfp-close,button.mfp-arrow{overflow:visible;cursor:pointer;background:transparent;border:0;-webkit-appearance:none;display:block;outline:none;padding:0;z-index:1046;box-shadow:none}button::-moz-focus-inner{padding:0;border:0}.mfp-close{background:#fff;color:#999;cursor:pointer;font-size:24px;font-style:normal;height:30px;line-height:30px;padding:0;position:absolute;right:1px;text-align:center;text-decoration:none;text-indent:2px;top:0;width:32px;z-index:12}.mfp-close:hover,.mfp-close:focus{opacity:1;filter:alpha(opacity=100)}.mfp-close:active{top:1px}.mfp-image-holder .mfp-close,.mfp-iframe-holder .mfp-close{color:#FFF;right:-6px;text-align:right;padding-right:6px;width:100%}.mfp-counter{position:absolute;top:0;right:0;color:#CCC;font-size:12px;line-height:18px;white-space:nowrap}.mfp-arrow{cursor:pointer;position:absolute;opacity:0.65;filter:alpha(opacity=65);margin:0;top:50%;margin-top:-55px;padding:0;width:90px;height:110px;-webkit-tap-highlight-color:transparent;opacity:0;z-index:10;-webkit-transition:all 300ms ease-out;transition:all 300ms ease-out}.rtm-single-media:hover .mfp-arrow{opacity:1}@media (max-device-width: 640px){.mfp-arrow{display:none}.rtm-single-media:hover .mfp-arrow{display:none}}.mfp-arrow:active{margin-top:-54px}.mfp-arrow:hover,.mfp-arrow:focus{opacity:1;filter:alpha(opacity=100)}.mfp-arrow:before,.mfp-arrow:after,.mfp-arrow .mfp-b,.mfp-arrow .mfp-a{content:'';display:block;width:0;height:0;position:absolute;left:0;top:0;margin-top:40%;margin-left:40%;border:medium inset transparent}.mfp-arrow:after,.mfp-arrow .mfp-a{border-top-width:13px;border-bottom-width:13px;top:8px}.mfp-arrow:before,.mfp-arrow .mfp-b{border-top-width:21px;border-bottom-width:21px;opacity:0.7}.mfp-arrow-left{left:0}.mfp-arrow-left:after,.mfp-arrow-left .mfp-a{border-right:17px solid #FFF;margin-left:32%}.mfp-arrow-left:before,.mfp-arrow-left .mfp-b{margin-left:25%;border-right:27px solid #3F3F3F}.mfp-arrow-right{right:0}.mfp-arrow-right:after,.mfp-arrow-right .mfp-a{border-left:17px solid #FFF;margin-left:44%}.mfp-arrow-right:before,.mfp-arrow-right .mfp-b{border-left:27px solid #3F3F3F}.mfp-iframe-holder{padding-top:40px;padding-bottom:40px}.mfp-iframe-holder .mfp-content{line-height:0;width:100%;max-width:900px}.mfp-iframe-holder .mfp-close{top:-40px}.mfp-iframe-scaler{width:100%;height:0;overflow:hidden;padding-top:56.25%}.mfp-iframe-scaler iframe{position:absolute;display:block;top:0;left:0;width:100%;height:100%;box-shadow:0 0 8px rgba(0,0,0,0.6);background:#000}img.mfp-img{width:auto;max-width:100%;height:auto;display:block;line-height:0;box-sizing:border-box;padding:40px 0 40px;margin:0 auto}.mfp-figure{line-height:0}.mfp-figure:after{content:'';position:absolute;left:0;top:40px;bottom:40px;display:block;right:0;width:auto;height:auto;z-index:-1;box-shadow:0 0 8px rgba(0,0,0,0.6);background:#444}.mfp-figure small{color:#BDBDBD;display:block;font-size:12px;line-height:14px}.mfp-figure figure{margin:0}.mfp-bottom-bar{margin-top:-36px;position:absolute;top:100%;left:0;width:100%;cursor:auto}.mfp-title{text-align:left;line-height:18px;color:#F3F3F3;word-wrap:break-word;padding-right:36px}.mfp-image-holder .mfp-content{max-width:100%}.mfp-gallery .mfp-image-holder .mfp-figure{cursor:pointer}.mfp-preloader{position:absolute;top:50%;left:0;right:0;margin-top:-36px;z-index:1044;font-size:0;width:36px;height:36px;margin-left:auto;margin-right:auto}.mfp-preloader:before{content:'Loading…';position:absolute;width:30px;height:30px}.mfp-preloader:not(:required):before{content:'';border-radius:50%;border:3px solid rgba(255,255,255,0.27);border-top-color:rgba(255,255,255,0.9);animation:spinner .6s linear infinite;-webkit-animation:spinner .6s linear infinite}@keyframes spinner{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes spinner{to{-webkit-transform:rotate(360deg)}}@media screen and (max-width: 800px) and (orientation: landscape), screen and (max-height: 300px){.mfp-img-mobile .mfp-image-holder{padding-left:0;padding-right:0}.mfp-img-mobile img.mfp-img{padding:0}.mfp-img-mobile .mfp-figure:after{top:0;bottom:0}.mfp-img-mobile .mfp-figure small{display:inline;margin-left:5px}.mfp-img-mobile .mfp-bottom-bar{background:rgba(0,0,0,0.6);bottom:0;margin:0;top:auto;padding:3px 5px;position:fixed;box-sizing:border-box}.mfp-img-mobile .mfp-bottom-bar:empty{padding:0}.mfp-img-mobile .mfp-counter{right:5px;top:3px}.mfp-img-mobile .mfp-close{top:0;right:0;width:35px;height:35px;line-height:35px;background:rgba(0,0,0,0.6);position:fixed;text-align:center;padding:0}}@media all and (max-width: 900px){.mfp-arrow{-webkit-transform:scale(0.75);-ms-transform:scale(0.75);transform:scale(0.75)}.mfp-arrow-left{-webkit-transform-origin:0;-ms-transform-origin:0;transform-origin:0}.mfp-arrow-right{-webkit-transform-origin:100%;-ms-transform-origin:100%;transform-origin:100%}.mfp-container{padding-left:6px;padding-right:6px}}#atwho-container #atwho-ground-comment_content .atwho-view{z-index:2147483647}.mfp-content .rtm-lightbox-container{background:#000;margin:0 auto;position:relative}.mfp-content .rtm-lightbox-container .rtmedia-comment-media-list .mejs-container.mejs-video{min-height:200px;min-width:200px}.mfp-content .rtm-single-meta{background:#fff;overflow:hidden;padding:20px 20px 110px;position:relative;vertical-align:top}.rtm-single-media{overflow:hidden;position:relative;text-align:center;vertical-align:middle}.rtm-single-media .mejs-container{margin:0 auto;max-width:inherit}.rtm-single-media .rtmedia-message-container{position:absolute;top:45%;left:0;right:0;margin-left:auto;margin-right:auto}@media (max-device-width: 640px){.rtm-single-media .rtmedia-message-container{top:25%}}.rtm-ltb-action-container{background-color:rgba(0,0,0,0.6);bottom:0;color:#fff;line-height:38px;opacity:0;padding:0 10px;position:absolute;width:100%;-webkit-transition:all 300ms ease-out;transition:all 300ms ease-out}.rtm-single-media:hover .rtm-ltb-action-container{opacity:1}@media (max-device-width: 640px){.rtm-ltb-action-container{clear:both;position:relative;opacity:1}.rtm-single-media:hover .rtm-ltb-action-container{opacity:1}}#buddypress #rtmedia-single-media-container.rtmedia-single-media .button{background:transparent;border:0 none;border-radius:2px;color:rgba(255,255,255,0.5);display:block;font-family:inherit;font-weight:normal;line-height:24px;margin:0;padding:0 6px;text-shadow:0 0 0;text-transform:none}#buddypress #rtmedia-single-media-container.rtmedia-single-media .button:hover{background:rgba(255,255,255,0.2);color:rgba(255,255,255,0.8)}#buddypress #rtmedia-single-media-container.rtmedia-single-media .rtm-options .button{color:#333;margin:0 auto;padding:0 4px 0 0}#buddypress #rtm-media-options-list .rtm-options form button{font-size:small}#buddypress #rtm-media-options-list .rtm-options .button{background:transparent;border:0 none;border-radius:2px;color:rgba(255,255,255,0.5);float:left;font-family:inherit;font-weight:normal;line-height:24px;padding:0 6px;text-shadow:0 0 0;text-transform:none}#buddypress #rtm-media-options-list .rtm-options .rtmedia-delete-favlist{color:#fff;padding:0}.rtm-options.rtm-options{background:#666;color:#fff;display:none;font-size:14px;list-style:none;margin:0;padding:8px 10px;position:absolute;left:0;top:38px;width:190px;z-index:10}.rtm-options li{margin:0;overflow:hidden;padding:2px 0}.rtm-media-options .rtm-options:after{bottom:100%;left:20px;border:solid transparent;content:' ';height:0;width:0;position:absolute;pointer-events:none;border-color:rgba(255,255,255,0);border-bottom-color:#666;border-width:6px;margin-left:-6px}.mfp-content .rtm-options{background:#fff;color:#333;bottom:38px;right:0;left:auto;top:auto}.mfp-content .rtm-options:after{top:100%;right:22px;border:solid transparent;content:' ';height:0;width:0;position:absolute;pointer-events:none;border-color:rgba(255,255,255,0);border-top-color:#fff;border-width:6px;margin-left:-6px}.rtm-options .dashicons{font-size:14px;line-height:24px;margin-right:2px}.rtm-media-options .rtm-options a{border:0;color:#fff;display:block;text-decoration:none}.rtm-ltb-title{color:rgba(255,255,255,0.7);float:left;font-size:13px}.rtm-ltb-title a{color:inherit}.rtm-ltb-title a:hover{border-bottom:1px dotted;color:#fff}.rtm-item-actions{float:right}.rtm-item-actions>div,.rtm-item-actions>form{float:left;margin:0 4px 0 0;padding:7px 0;position:relative}.rtmedia-media{margin:0 auto}.rtmedia-media img{display:inline-block;max-height:inherit;height:auto;max-width:100%;width:auto}@media only screen and (max-device-width: 1024px){.rtmedia-media{margin:40px 0}}.rtm-user-meta-details .username{font-size:16px;line-height:1;margin-bottom:6px}.userprofile{float:left;margin:0 16px 16px 0;max-width:54px}.userprofile a{display:block}.userprofile img{height:auto;max-width:100%}.rtm-time-privacy{color:#999;font-size:12px}.rtm-time-privacy .dashicons{font-size:14px;line-height:1.5;margin-top:-2px}.rtmedia-actions-before-comments>span{float:left;margin-right:10px}.rtmedia-actions-before-comments .rtmedia-comment-link,.rtmedia-actions-before-comments .rtmedia-view-conversation,#buddypress .rtmedia-actions-before-comments .rtmedia-like{border:0;font-size:13px;font-weight:normal;line-height:2;padding:0;text-transform:none}.rtmedia-actions-before-comments .rtmedia-comment-link:hover,.rtmedia-actions-before-comments .rtmedia-view-conversation:hover,#buddypress .rtmedia-actions-before-comments .rtmedia-like:hover{background:transparent}.rtmedia-comment-user-pic{float:left;margin-right:10px;max-width:36px}.rtmedia-comment-user-pic img{height:auto;max-width:100%}.rtm-like-comments-info{position:relative}.rtm-like-comments-info:after{bottom:100%;left:15px;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none;border-color:rgba(237,239,244,0);border-bottom-color:#edeff4;border-width:4px;margin-left:-4px}.rtm-comment-list.rtm-comment-list{height:340px;list-style:none;margin:0;overflow:auto;padding:0}.rtm-comment-list li{background:#edeff4;font-size:12px;margin-bottom:1px;padding:10px;position:relative}.rtm-comment-list li:hover .rtmedia-delete-comment{opacity:1}.rtm-comment-list .rtmedia-no-comments{margin:0;padding:5px 10px}.rtmedia-like-info{background:#edeff4;font-size:12px;margin-bottom:1px;padding:5px 10px;position:relative}.rtm-comment-wrap{overflow:hidden}.rtm-comment-wrap .rtmedia-comment-author{font-weight:700}.rtm-comment-wrap .rtmedia-comment-date{color:#999;font-size:11px}.rtmedia-comment-content{margin-top:2px}.rtmedia-delete-comment{color:#999;cursor:pointer;font-size:16px;opacity:0;position:absolute;right:5px;top:5px}.rtmedia-comment-content p{margin:0}.rtmedia-comment-details{line-height:1.5;margin-top:-3px}.rt_media_comment_form textarea{display:inline-block;margin-bottom:5px}.rtmedia-item-comments textarea{font-size:14px;padding:4px}.rtm-media-single-comments{bottom:20px;padding:10px;width:100%}.rtm-media-single-comments textarea{background-color:#edeff4;font-size:12px;line-height:14px;max-height:40px;min-height:30px;padding:4px}.rtmedia-popup{background:#fff;margin:20px auto;max-width:600px;padding:20px;position:relative;width:auto}.rtmedia-popup .rtm-modal-title{font-size:24px;margin-bottom:20px;margin-top:0}.rtmedia-popup label{display:block;margin-bottom:5px}#rtm-modal-container p{margin-bottom:10px}#rtm-mejs-video-container{margin:0 auto}.rtmedia-media-name{float:left;max-width:140px;overflow:hidden;text-align:left;text-overflow:ellipsis;white-space:nowrap}.rtm-single-media.rtm-media-type-video{padding-bottom:40px;padding-top:40px}.rtmedia-gallery-alert-container{position:fixed;top:0;left:0;height:100%;width:100%;background-color:rgba(0,0,0,0.6);z-index:999997}.rtmedia-gallery-message-box{position:fixed;top:40%;left:50%;margin-left:auto;margin-right:auto;z-index:999999}.rtmedia-gallery-message-box span{position:relative;left:-50%}#mobile-swipe-overlay{position:absolute;display:none;width:100%;height:100%;top:0;left:0;right:0;bottom:0;background-color:rgba(255,255,255,0.7);z-index:15;cursor:pointer}#mobile-swipe-overlay .swipe-icon{position:absolute;top:30%;left:50%;font-size:50px;color:#000;-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%);-ms-transform:translate(-50%, -50%);width:200px}#mobile-swipe-overlay .swipe-icon img{width:100%}#mobile-swipe-overlay .swipe-tootlip{font-weight:800;position:absolute;padding:20px;top:45%;width:100%;text-align:center}.rtmedia-activity-container{box-sizing:border-box}.rtmedia-activity-container *,.rtmedia-activity-container *:before,.rtmedia-activity-container *:after{box-sizing:inherit}.rtmedia-activity-container .rtmedia-list.masonry{list-style:none;padding:0}.rtmedia-activity-container .rtmedia-list.masonry p{display:none}.rtmedia-activity-container .rtmedia-list.masonry:after{content:'';display:block;clear:both}.rtmedia-activity-container .rtmedia-list-item.masonry-brick{display:inline-block;float:left;width:32%;padding:0 !important}.rtmedia-activity-container .rtmedia-list-item.masonry-brick .mejs-container{min-width:33% !important;margin:0 0 5px 0;width:100% !important}.rtmedia-activity-container .rtmedia-list-item.masonry-brick .mejs-container .mejs-controls{width:100%}.rtmedia-activity-container .rtmedia-list-item.masonry-brick .mejs-container .mejs-controls .mejs-time-total{display:none}.rtmedia-activity-container .rtmedia-list-item.masonry-brick .mejs-container .mejs-controls .mejs-horizontal-volume-slider{width:20%;padding-left:5px}.rtmedia-activity-container .rtmedia-list-item.masonry-brick .mejs-container .mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-total{width:100%}.rtmedia-activity-container .rtmedia-list-item.masonry-brick .mejs-container .mejs-controls .mejs-horizontal-volume-slider .mejs-time-loaded{display:none}.rtmedia-activity-container .rtmedia-list-item.masonry-brick img{display:block;max-width:100%}.rtmedia-activity-container .rtmedia-list-item.masonry-brick .rtmedia-item-title{display:none}#buddypress ul.rtmedia-list li{border-bottom:0;padding-bottom:0}.rtmedia-activity-container .rtmedia-item-actions{display:none}.rtmedia-activity-container .rtmedia-item-title,.rtmedia-activity-container .rtmedia-item-title a{border:0;color:#666;font-size:13px;margin:5px 0 0;overflow:hidden;text-align:center;text-overflow:ellipsis;white-space:nowrap}#rtmedia-whts-new-upload-container div{left:0 !important;position:absolute;top:0 !important}#aw-whats-new-submit,.rtmedia-add-media-button{display:block}.rtm-drag-drop-active{border:4px dashed green !important;display:block;height:100%;opacity:0.5;z-index:9999}#rtm-drop-files-title{background:rgba(0,0,0,0.2);display:none;font-size:14px;height:100%;padding:20px;position:absolute;top:0;width:100%}#rtSelectPrivacy{float:right}form.rt_media_comment_form .rtmedia-plupload-container{overflow:hidden}.rtmedia-plupload-container{position:relative;float:left}.rtm-upload-button-wrapper{float:left;margin-right:5px}#rtmedia-action-update{margin-right:10px}.rtmedia-list-item.media-type-photo,.rtmedia-list-item.media-type-document,.rtmedia-list-item.media-type-music,.rtmedia-list-item.media-type-video{display:inline-block}.media-type-music .mejs-container{margin-bottom:10px}.previous-pagination{float:left;margin-top:10px}.next-pagination{float:right;margin-top:10px}@media screen and (max-width: 500px){#activity-stream li .media-type-video{width:100%}#activity-stream li .media-type-video .mejs-video{max-width:100%;min-width:100%}}#rtmedia_show_all_comment{cursor:pointer}#rtmedia_show_all_comment:hover{text-decoration:underline}#whats-new-options{opacity:0;display:none}#whats-new-options .rtmedia-uploader-div{opacity:0;display:none;visibility:hidden}.bp-nouveau .activity-update-form .rtmedia-uploader-div{margin-left:8.5%}.bp-nouveau .activity-update-form .rtmedia-plupload-container{width:25%}.bp-nouveau .activity-update-form .rtmedia-upload-terms #rtmedia_upload_terms_conditions{margin-left:20px}.bp-nouveau .activity-update-form #aw-whats-new-submit{margin-top:15px}.ac-form .rtmedia-uploader-div,.rt_media_comment_form .rtmedia-uploader-div{opacity:1;display:block;visibility:visible}#whats-new-options{opacity:0;display:none}a.rtmedia-comment-link{display:none}a.rtmedia-comment-link.rtmedia-comments-link{display:initial}.rtmedia-album-edit .rtm-checkbox-wrap{background:rgba(255,255,255,0.9);height:30px;line-height:1;padding:10px;position:absolute;z-index:10}.rtmedia-album-edit .rtmedia-item-selector{position:relative;top:-7px}.rtmedia-album-edit .rtmedia-move-container{display:none}.rtm-single-actions.rtm-item-actions{float:none}.rtm-media-type-music .rtmedia-media{width:100%}.media-item .describe{border-collapse:collapse;width:100%;border-top-style:solid;border-top-width:1px;clear:both;cursor:default}.media-item.media-blank .describe{border:0}.media-item .describe th{vertical-align:top;text-align:left;padding:5px 10px 10px;width:140px}.media-item .describe .align th{padding-top:0}.media-item .media-item-info tr{background-color:transparent}.media-item .describe td{padding:0 8px 8px 0;vertical-align:top}.media-item thead.media-item-info td{padding:4px 10px 0}.media-item .media-item-info .A1B1{padding:0 0 0 10px}.media-item td.savesend{padding-bottom:15px}.media-item .thumbnail{max-height:128px;max-width:128px}#wpbody-content #async-upload-wrap a{display:none}.media-upload-form{margin-top:20px}.media-upload-form td label{margin-right:6px;margin-left:2px}.media-upload-form .align .field label{display:inline;padding:0 0 0 23px;margin:0 1em 0 3px;font-weight:bold}.media-upload-form tr.image-size label{margin:0 0 0 5px;font-weight:bold}.media-upload-form th.label label{font-weight:bold;margin:0.5em;font-size:13px}.media-upload-form th.label label span{padding:0 5px}abbr.required{border:medium none;text-decoration:none}.media-item .describe input[type="text"],.media-item .describe textarea{width:460px}.media-item .describe p.help{margin:0;padding:0 0 0 5px}.media-item .edit-attachment,.describe-toggle-on,.describe-toggle-off{display:block;line-height:36px;float:right;margin-right:15px}.media-item .describe-toggle-off,.media-item.open .describe-toggle-on{display:none}.media-item.open .describe-toggle-off{display:block}#media-items .media-item{border-style:solid;border-width:1px;min-height:36px;position:relative;margin-top:-1px;width:100%}#media-items{width:623px}.media-new-php #media-items{margin:1em 0}#media-items:empty{border:0 none}.media-item .filename{line-height:36px;overflow:hidden;padding:0 10px}.media-item .error-div{padding-left:10px}.media-item .pinkynail{float:left;margin:2px 2px 0;max-width:40px;max-height:32px}.media-item .startopen,.media-item .startclosed{display:none}.media-item .original{position:relative;height:34px}.media-item .progress{float:right;height:22px;margin:6px 10px 0 0;width:200px;line-height:2em;padding:0;overflow:hidden;margin-bottom:2px;border:1px solid #d1d1d1;background:#f7f7f7;background-image:-webkit-gradient(linear, left bottom, left top, from(#fff), to(#f7f7f7));background-image:-webkit-linear-gradient(bottom, #fff, #f7f7f7);background-image:linear-gradient(to top, #fff, #f7f7f7);border-radius:3px;box-shadow:inset 0 0 3px rgba(0,0,0,0.1)}.media-item .bar{z-index:9;width:0;height:100%;margin-top:-24px;background-color:#8cc1e9;background-image:-webkit-gradient(linear, left bottom, left top, from(#72a7cf), to(#8cc1e9));background-image:-webkit-linear-gradient(bottom, #72a7cf, #8cc1e9);background-image:linear-gradient(to top, #72a7cf, #8cc1e9);border-radius:3px;box-shadow:0 0 3px rgba(0,0,0,0.3)}.media-item .progress .percent{z-index:10;position:relative;width:200px;padding:0 8px;text-shadow:0 1px 0 rgba(255,255,255,0.4);color:rgba(0,0,0,0.6)}.upload-php .fixed .column-parent{width:15%}.js .html-uploader #plupload-upload-ui{display:none}.js .html-uploader #html-upload-ui{display:block}.media-upload-form .media-item.error{margin:0;padding:0}.media-upload-form .media-item.error p,.media-item .error-div{line-height:16px;margin:5px 10px;padding:0}.media-item .error-div a.dismiss{display:block;float:right;margin:5px 4px 0 15px}.find-box{width:600px;height:300px;overflow:hidden;padding:33px 0 51px;position:absolute;z-index:1000}.find-box-head{cursor:move;font-weight:bold;height:2em;line-height:2em;padding:1px 12px;position:absolute;top:5px;width:100%}.find-box-inside{overflow:auto;padding:6px;height:100%}.find-box-search{overflow:hidden;padding:9px;position:relative}.find-box-search .spinner{float:none;left:125px;position:absolute;top:9px}#find-posts-input{float:left;width:140px;height:24px}#find-posts-search{float:left;margin:1px 4px 0 3px}#find-posts-response{margin:8px 0;padding:0 1px 6px}#find-posts-response table{width:100%}#find-posts-response .found-radio{padding:3px 0 0 8px;width:15px}.find-box-buttons{padding:8px;overflow:hidden}.find-box #resize-se{position:absolute;right:1px;bottom:1px}.ui-find-overlay{position:absolute;top:0;left:0;background-color:#000;opacity:0.6;filter:alpha(opacity=60)}ul#dismissed-updates{display:none}form.upgrade{margin-top:8px}form.upgrade .hint{font-style:italic;font-size:85%;margin:-0.5em 0 2em 0}#poststuff .inside .the-tagcloud{margin:5px 0 10px;padding:8px;border-width:1px;border-style:solid;line-height:1.8em;word-spacing:3px;border-radius:6px}.drag-drop #drag-drop-area{border:4px dashed #DDDDDD;height:200px}.drag-drop .drag-drop-inside{margin:70px auto 0;width:250px}.drag-drop-inside p{color:#aaa;font-size:14px;margin:5px 0;display:none}.drag-drop .drag-drop-inside p{text-align:center}.drag-drop-inside p.drag-drop-info{font-size:20px}.drag-drop .drag-drop-inside p,.drag-drop-inside p.drag-drop-buttons{display:block}.drag-drop.drag-over #drag-drop-area{border-color:#83b4d8}#plupload-upload-ui{position:relative}.describe .image-editor{vertical-align:top}.imgedit-wrap{position:relative}#item-body .imgedit-settings .imgedit-group-top h2{display:inline-block;margin:0}.rtmedia-container .rtmedia-image-editor-cotnainer label{display:inline-block;float:none;margin-right:0}.rtmedia-container .rtmedia-image-editor-cotnainer .dashicons-editor-help{padding:0;height:auto;margin-top:10px}.rtmedia-container .rtmedia-image-editor-cotnainer .hidden{display:none}.imgedit-settings p{margin:8px 0}.post-php .imgedit-wrap table{width:100%}.describe .imgedit-wrap table td,.wp_attachment_holder .imgedit-wrap table td{vertical-align:top;padding-top:0}.describe .imgedit-wrap table td.imgedit-settings{padding:0 5px}.wp_attachment_holder .imgedit-wrap table td.imgedit-settings{width:250px}td.imgedit-settings input{margin-top:0;vertical-align:middle}.imgedit-wait{position:absolute;top:0;background:#fff url(../../../../../../wp-admin/images/wpspin_light.gif) no-repeat scroll 22px 10px;background-size:16px 16px;opacity:0.7;filter:alpha(opacity=70);width:100%;height:500px;display:none}.spinner{background:url(../../../../../../wp-admin/images/wpspin_light.gif) no-repeat;background-size:16px 16px;display:none;float:right;opacity:0.7;filter:alpha(opacity=70);width:16px;height:16px;margin:5px 5px 0}.no-float{float:none}.media-disabled,.imgedit-settings .disabled{color:grey}.wp_attachment_image,.A1B1{overflow:hidden}.wp_attachment_image .button,.A1B1 .button{float:left}.no-js .wp_attachment_image .button{display:none}.wp_attachment_image .spinner,.A1B1 .spinner{float:left;padding:0 4px 4px;vertical-align:bottom}.imgedit-menu{margin:0 0 12px;min-width:300px}.imgedit-menu div{float:left;width:32px;height:32px}.imgedit-crop-wrap{position:relative}.imgedit-crop{margin:0 8px 0 0}.imgedit-crop.disabled:hover{background-position:-9px -31px}.imgedit-crop:hover{background-position:-9px -1px}.imgedit-rleft{margin:0 3px}.imgedit-rleft.disabled:hover{background-position:-46px -31px}.imgedit-rleft:hover{background-position:-46px -1px}.imgedit-rright{margin:0 8px 0 3px}.imgedit-rright.disabled:hover{background-position:-77px -31px}.imgedit-rright:hover{background-position:-77px -1px}.imgedit-flipv{margin:0 3px}.imgedit-flipv.disabled:hover{background-position:-115px -31px}.imgedit-flipv:hover{background-position:-115px -1px}.imgedit-fliph{margin:0 8px 0 3px}.imgedit-fliph.disabled:hover{background-position:-147px -31px}.imgedit-fliph:hover{background-position:-147px -1px}.imgedit-undo{margin:0 3px}.imgedit-undo.disabled:hover{background-position:-184px -31px}.imgedit-undo:hover{background-position:-184px -1px}.imgedit-redo{margin:0 8px 0 3px}.imgedit-redo.disabled:hover{background-position:-215px -31px}.imgedit-redo:hover{background-position:-215px -1px}.imgedit-applyto img{margin:0 8px 0 0}.imgedit-group h3{font-size:18px}.imgedit-group .dashicons{border:0;line-height:1.2}.imgedit-group-top{margin:5px 0}.imgedit-applyto .imgedit-label{padding:2px 0 0;display:block}.imgedit-help{display:none;font-style:italic;margin-bottom:8px}a.imgedit-help-toggle{text-decoration:none}.form-table td.imgedit-response{padding:0}.imgedit-submit{margin:8px 0}.imgedit-submit-btn{margin-left:20px}.imgedit-wrap .nowrap{white-space:nowrap}span.imgedit-scale-warn{color:red;font-size:20px;font-style:normal;visibility:hidden;vertical-align:middle}.wp_attachment_details{margin-bottom:20px}.imgedit-menu div{border-color:#d5d5d5;background-color:#f1f1f1}.imgedit-menu div:hover{border-color:#c1c1c1;background-color:#eaeaea}.imgedit-menu div.disabled{border-color:#ccc;background-color:#ddd;filter:alpha(opacity=50);opacity:0.5}.bp-media-image-editor-cotnainer{margin-top:35px}.wp_attachment_image .bp-media-image-edit{float:left}.wp_attachment_image .spinner{display:none}.bp-media-image-editor-cotnainer .hidden{display:none}.bp-media-image-editor-cotnainer div.updated{margin:5px 0 15px;background-color:#ffffe0;border-color:#e6db55;padding:0 .6em;border-radius:3px;border-width:1px;border-style:solid}.bp-media-image-editor-cotnainer div.updated p{margin:.5em 0;padding:2px}body article.bp_members.bp_member .entry-content,body div.bp_members.bp_member .entry-content{width:100%}.rtm-media-gallery-uploader{display:none}.rtmedia-uploader .drag-drop{border:4px dashed #DDD;text-align:center;background:#fafafa;overflow:hidden;color:#AAAAAA;margin-top:20px;padding:25px 0}.rtmedia-uploader .drag-drop.dragover{border-color:#83b4d8}.rtmedia-uploader .drag-drop .drag-drop-info{font-size:20px;line-height:24px}.rtmedia-uploader .drag-drop .rtm-select-files span{vertical-align:middle}.rtmedia-uploader .drag-drop .rtm-seperator{margin:0px 20px}.rtmedia-uploader .drag-drop .start-media-upload{display:none;margin-top:20px}.rtmedia-uploader .drag-drop .rtm-file-size-limit{vertical-align:middle;font-size:16px;line-height:24px}.rtm-uploader-main-wrapper .rtm-uploader-tabs{margin-bottom:10px;text-align:left}.rtm-uploader-main-wrapper ul{border-bottom:1px solid #CCC}.rtm-uploader-main-wrapper li{margin:0 0 -1px 10px;display:inline-block;padding:5px 10px;line-height:25px;background-color:#e4e4e4;border:1px solid #CCC}.rtm-uploader-main-wrapper li.active{background:transparent;border-left:1px solid #CCC;border-top:1px solid #CCC;border-right:1px solid #CCC;border-bottom:1px solid #fafafa}.rtm-uploader-main-wrapper li:hover{cursor:pointer}.rtmedia-container .rtmedia-list{margin:10px -5px}.rtmedia-container .rtmedia-list .rtmedia-list-item{float:left;margin:5px;position:relative}.rtmedia-container .rtmedia-list .rtmedia-list-item>a{display:block}.rtmedia-container .rtmedia-list .rtmedia_time{background-color:#000;color:#fff;display:inline-block;font-size:11px;font-weight:bold;line-height:14px;opacity:0.75;padding:0 4px;position:absolute;right:2px;top:2px}.rtmedia-container .rtmedia-list img{vertical-align:top}.rtmedia-container .rtmedia-list .rtmedia-item-title h4{color:#666;font-size:12px;font-weight:normal;margin:5px 0 0;overflow:hidden;text-align:center;text-overflow:ellipsis;white-space:nowrap}.rtm-load-more{background:#eee;text-align:center}.rtmedia-container .rtm-load-more a{border:0;padding:10px 0}.rtm-load-more .rtm-media-loading{padding:10px 0}.rtm-media-options.rtm-media-search-enable>*:nth-last-child(2){border-right:none}.rtm-media-options{line-height:1.4;margin-bottom:10px;clear:both}.rtm-media-options>div{display:inline-block;cursor:pointer}.rtm-media-options .rtm-media-options-list{margin-right:5px;padding-right:10px;position:relative}.rtm-media-options>*{border-right:1px solid #999}.rtm-media-options>*:last-child{border-right:none}.rtm-media-options .dashicons{font-size:inherit;line-height:1.4}#buddypress .media_search.media_search .search_by{margin-top:3px}.bp-legacy.media #buddypress #item-header-cover-image .user-nicename{margin-bottom:20px}.bp-legacy.media #buddypress div#item-header div#item-header-content ul li,.bp-legacy.media #buddypress div#item-header div#item-header-content ul div{float:left;margin:2px 10px}.bp-legacy.media #buddypress div#item-header div#item-header-content button,.bp-legacy.media #buddypress div#item-header div#item-header-content a{background:#fff;border:1px solid #ccc;color:#767676;font-size:small;cursor:pointer;outline:none;padding:4px 10px;text-align:center;text-decoration:none}.bp-legacy.media #buddypress div#item-header div#item-header-content button:hover,.bp-legacy.media #buddypress div#item-header div#item-header-content a:hover{background:#ededed;border:1px solid #bbb;color:#555;outline:none}.bp-nouveau.media .entry-title{font-size:34px;font-weight:inherit;margin-bottom:0}.bp-nouveau.media .entry-title a{color:#767676}.bp-nouveau.media #buddypress #item-header-cover-image .user-nicename{margin-top:15px;margin-bottom:30px}.bp-nouveau.media #buddypress div#item-header div#item-header-content ul li,.bp-nouveau.media #buddypress div#item-header div#item-header-content ul div{float:left;margin:2px 10px}.bp-nouveau.media #buddypress div#item-header div#item-header-content button,.bp-nouveau.media #buddypress div#item-header div#item-header-content a{background:#fff;border-color:#ccc;border-style:solid;border-width:1px;color:#555;cursor:pointer;font-size:inherit;font-weight:400;outline:none;padding:0.3em 0.5em;text-align:center;text-decoration:none;width:auto}.bp-nouveau.media #buddypress div#item-header div#item-header-content button:hover,.bp-nouveau.media #buddypress div#item-header div#item-header-content a:hover{background:#ededed;border-color:#999999;color:#333;outline:none;text-decoration:none}.media_search.media_search{float:right;border:1px solid #ccc;margin-left:5px;padding:3px 0}.media_search.media_search .media_search_input{width:200px;outline:0;max-width:200px;margin:0;box-shadow:none;padding:5px 6px;border:none;background:transparent;float:left;max-height:30px}.media_search.media_search #media_fatch_loader.load{float:left;width:20px;height:30px;position:relative}.media_search.media_search #media_fatch_loader.load:before{content:'';border-radius:50%;border:1px solid #aaa;border-top-color:rgba(255,255,255,0.9);animation:spinner .8s linear infinite;-webkit-animation:spinner .8s linear infinite;position:absolute;width:15px;height:15px;top:24%}.media_search.media_search .search_option{padding:0;background:transparent;color:#000;margin-bottom:0;line-height:1;border:none}.media_search.media_search .media_search_remove.search_option{display:none}.media_search.media_search .media_search_remove.search_option i{margin-top:4px}.media_search.media_search .search_by{background:transparent;margin-top:3px;float:left;width:auto;margin-bottom:0;height:auto;padding-top:0;padding-bottom:0}@keyframes spinner{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes spinner{to{-webkit-transform:rotate(360deg)}}.rtmedia-upload-media-link{cursor:pointer}a.rtmedia-upload-media-link{border:none}.rtm-album-privacy span{font-size:16px;display:inline-block;margin:0 20px 20px 20px;vertical-align:top}.rtm-album-privacy label{margin-right:8px}.rtm-album-privacy .dashicons{font-size:16px;line-height:1.6;margin-right:5px}#rtm-media-options-list .rtmedia-delete-album{background:transparent;border:0;color:#fff;font-family:inherit;font-size:inherit;font-weight:inherit;padding:0;text-transform:inherit}#rtm-media-options-list .rtmedia-delete-album:hover{background:transparent;border:0;color:#fff}.rtmedia-single-container button.rtmedia-like{background-color:transparent;color:inherit}#buddypress #item-body{padding:0 20px}#buddypress .mejs-controls button{padding:4px 8px;border:none;background:transparent url("../../../lib/media-element/mejs-controls.png") no-repeat}#buddypress .mejs-controls .mejs-play>button{background-position:0 0}#buddypress .mejs-controls .mejs-pause>button{background-position:-20px 0}#buddypress .mejs-controls .mejs-unmute>button{background-position:-40px 0}#buddypress .mejs-controls .mejs-mute>button{background-position:-60px 0}#buddypress .mejs-controls .mejs-fullscreen-button>button{background-position:-80px 0}#buddypress .mejs-controls .mejs-unfullscreen>button{background-position:-100px 0}#buddypress .mejs-controls .mejs-replay>button{background-position:-160px 0}.mejs-container .mejs-controls .mejs-time{padding:15px 3px 0;content:''}.rtmedia-activity-container .mejs-playpause-button.mejs-play button:before,.rtmedia-activity-container .mejs-playpause-button.mejs-pause button:before,.rtmedia-activity-container .mejs-volume-button.mejs-mute button:before,.rtmedia-activity-container .mejs-fullscreen-button button:before,.rtmedia-media .mejs-playpause-button.mejs-play button:before,.rtmedia-media .mejs-playpause-button.mejs-pause button:before,.rtmedia-media .mejs-volume-button.mejs-mute button:before,.rtmedia-media .mejs-fullscreen-button button:before{content:''}@media only screen and (min-width: 1025px){.mfp-content .rtm-lightbox-container{display:-webkit-box;display:-ms-flexbox;display:flex;table-layout:fixed;width:100%;min-height:473px}.mfp-content .rtm-mfp-close{background:transparent}.mfp-content .rtm-single-media{display:-webkit-box;display:-ms-flexbox;display:flex;width:66.6667%;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.mfp-content .rtm-single-meta{display:block;width:33.3333%;padding:20px}.mfp-content .rtm-single-meta .rtmedia-scroll{height:100%;overflow-X:hidden}}.rtl #rtSelectPrivacy{float:left}.rtl .rtmedia-plupload-container{float:right}.rtl .rtm-upload-button-wrapper{float:right}.rtl #whats-new-post-in-box{float:right}.rtl .describe-toggle-off{float:left}.rtl .media-item .pinkynail{float:right}.rtl .media-item .progress{float:left}.rtl .media-item .error-div a.dismiss{float:left}.rtl #find-posts-input{float:right}.rtl #find-posts-search{float:right}.rtl .spinner{float:left}.rtl .wp_attachment_image .button,.rtl .A1B1 .button{float:right}.rtl .wp_attachment_image .spinner,.rtl .A1B1 .spinner{float:right}.rtl .imgedit-menu div{float:right}.rtl .wp_attachment_image .bp-media-image-edit{float:right}.rtl .rtmedia-container .rtmedia-list .rtmedia-list-item{float:right}.rtl #buddypress #rtm-media-options-list .rtm-options .button{float:right}.rtl .rtm-ltb-title{float:right}.rtl .rtm-item-actions{float:left}.rtl .rtm-item-actions>div,.rtl .rtm-item-actions>form{float:right}.rtl .userprofile{float:right}.rtl .rtmedia-actions-before-comments>span{float:right}.rtl .rtmedia-comment-user-pic{float:right}.rtl .rtmedia-media-name{float:right}.rtl #rtmedia-uploader-form .rtm-plupload-list li,.rtl #rtmedia_uploader_filelist li{float:right}.rtl .rtm-page-number{float:right}.rtl .rtm-page-number .rtmedia-page-link{float:right}.rtl .rtm-pagination{float:right}.rtl .rtm-pagination .rtm-paginate{float:left}.rtl .rtm-tabs li{float:right}.rtl .alignleft{float:right}.rtl .alignright{float:left}
|
1 |
+
.alignleft{float:left}.alignright{float:right}.aligncenter{display:block;margin-left:auto;margin-right:auto;text-align:center}.clear-both{clear:both}.clear-none{clear:none}.clear-left{clear:left}.clear-right{clear:right}.rtm-inline-block{display:inline-block}.rtm-text-left{text-align:left}.rtm-text-right{text-align:right}.rtm-text-center{text-align:center}.rtm-border-0{border:0 !important}.hide{display:none}.rtmedia-success,.rtmedia-warning{margin:10px 0;padding:8px 14px 8px 14px;text-shadow:0 1px 0 rgba(255,255,255,0.5);border-bottom:1px solid #e7e7e7;cursor:pointer}.rtmedia-success{background-color:#dff0d8;color:#468847}.rtmedia-warning{background-color:#F0D8DD;color:#884646}.clearfix:after{content:"";display:table;clear:both}#buddypress form#whats-new-form textarea{box-sizing:border-box;min-height:70px;width:100%}#buddypress #whats-new-form .rtmedia-uploader-div{display:none}#buddypress #whats-new-form #whats-new-options .rtmedia-uploader-div{display:block}#buddypress #whats-new-options{height:auto !important;overflow:hidden}#buddypress form#whats-new-form p.activity-greeting{line-height:1}#buddypress form#whats-new-form #whats-new-options select{border:1px solid #ccc;font-size:13px;margin-top:0;padding:3px 2px}#whats-new-submit #aw-whats-new-submit{font-size:12px;line-height:18px;padding:4px 6px}#whats-new-post-in-box{float:left;font-size:13px}#buddypress form#whats-new-form #whats-new-submit{margin-top:0}#whats-new-textarea{margin-bottom:10px}body.media.buddypress{overflow-y:auto}#buddypress input[type=submit]:focus{background:#ededed;border:1px solid #bbb;color:#555;outline:0;text-decoration:none}#buddypress ul.activity-list li.activity-item .activity-comments .rtmedia-uploader-div{color:#767676;margin-left:50px;padding-left:15px}#buddypress form#whats-new-form #whats-new-content.active #whats-new-options[style] #whats-new-post-in-box{margin-top:0}#whats-new-post-in-box{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.rtmedia-container{box-sizing:border-box}.rtmedia-container *,.rtmedia-container *:before,.rtmedia-container *:after{box-sizing:inherit}.rtmedia-list.rtmedia-list{list-style:none;margin:0;padding:0}.rtmedia-list-item>a{border:0;display:inline-block;text-decoration:none}.rtmedia-list-item>a:focus{outline:0}.rtmedia-list-item>a+p{display:none}.rtmedia-list-item>a .rtmedia-item-thumbnail{width:150px;text-align:center}.rtmedia-list-item>a .rtmedia-item-thumbnail img{display:inline-block;max-height:inherit}#rtmedia-uploader-form .rtm-plupload-list,form .rtmedia-container .rtm-plupload-list,#rtmedia_uploader_filelist{list-style:none;margin-left:-4px;margin-right:-4px;padding-left:0;padding-top:10px}#rtmedia-uploader-form .rtm-plupload-list li,form .rtmedia-container .rtm-plupload-list li,#rtmedia_uploader_filelist li{background:#eee;float:left;margin:4px;max-width:110px;padding:5px;z-index:1;position:relative}#rtmedia-uploader-form .rtm-plupload-list li.upload-error,form .rtmedia-container .rtm-plupload-list li.upload-error,#rtmedia_uploader_filelist li.upload-error{border:1px solid red}#rtmedia-uploader-form .rtm-plupload-list img,form .rtmedia-container .rtm-plupload-list img,#rtmedia_uploader_filelist img{max-width:100%}#rtmedia-uploader-form .rtm-plupload-list canvas,form .rtmedia-container .rtm-plupload-list canvas,#rtmedia_uploader_filelist canvas{display:block;max-width:100%}#rtmedia-uploader-form .rtm-plupload-list .rtm-upload-edit-title,form .rtmedia-container .rtm-plupload-list .rtm-upload-edit-title,#rtmedia_uploader_filelist .rtm-upload-edit-title{font-size:12px}#rtmedia-uploader-form .rtm-plupload-list .rtm-upload-edit-desc,form .rtmedia-container .rtm-plupload-list .rtm-upload-edit-desc,#rtmedia_uploader_filelist .rtm-upload-edit-desc{font-size:12px;display:block}#rtmedia-uploader-form .rtm-plupload-list .rtm-upload-edit-title-wrapper label,#rtmedia-uploader-form .rtm-plupload-list .rtm-upload-edit-desc-wrapper label,form .rtmedia-container .rtm-plupload-list .rtm-upload-edit-title-wrapper label,form .rtmedia-container .rtm-plupload-list .rtm-upload-edit-desc-wrapper label,#rtmedia_uploader_filelist .rtm-upload-edit-title-wrapper label,#rtmedia_uploader_filelist .rtm-upload-edit-desc-wrapper label{display:block}#rtmedia-uploader-form .rtm-plupload-list .rtm-upload-edit-title-wrapper input.rtm-upload-edit-title,#rtmedia-uploader-form .rtm-plupload-list .rtm-upload-edit-desc-wrapper input.rtm-upload-edit-title,form .rtmedia-container .rtm-plupload-list .rtm-upload-edit-title-wrapper input.rtm-upload-edit-title,form .rtmedia-container .rtm-plupload-list .rtm-upload-edit-desc-wrapper input.rtm-upload-edit-title,#rtmedia_uploader_filelist .rtm-upload-edit-title-wrapper input.rtm-upload-edit-title,#rtmedia_uploader_filelist .rtm-upload-edit-desc-wrapper input.rtm-upload-edit-title{min-width:100%;margin-top:1px}.rtm-plupload-list:empty{display:none}.rtmedia-uploader-div,.rtmedia-uploader{clear:both}.rtm-upload-button-wrapper button.rtmedia-comment-media-upload,button.rtmedia-comment-media-upload{padding:3px 6px}.rtm-upload-button-wrapper button.rtmedia-comment-media-upload .dashicons,button.rtmedia-comment-media-upload .dashicons{font-size:18px;line-height:20px}button#rtmedia-add-media-button-post-update{padding:3px 6px}button#rtmedia-add-media-button-post-update .dashicons{font-size:18px;line-height:20px}.plupload_file_name{font-size:11px;font-weight:bold;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.plupload_file_size{color:#666;font-size:10px}.plupload_file_action{background:#eee;position:absolute;height:18px;right:4px;top:0;width:18px;z-index:10}.plupload_file_action .dashicons{color:#DD3D36;cursor:pointer;font-size:16px;height:18px;padding:2px 1px;width:18px}.plupload_file_status{height:15px;margin-bottom:5px;overflow:hidden}.plupload_file_progress{background:#7AD03A;height:100%;font-size:10px;line-height:15px;text-align:center;word-wrap:initial}.rtm-form .rtm-field-wrap{margin-bottom:20px}#buddypress a.rtm-button-back{padding:3px 10px}#buddypress div.rtmedia-page-no.rtm-page-number a.rtmedia-page-link.button{padding:5px 10px}.rtmedia_next_prev{padding:0 10px}.rtm-page-number{float:left}.rtm-page-number .rtm-label{line-height:30px}.rtm-page-number .rtm-label,.rtm-page-number .rtm-go-to-num,.rtm-page-number .rtmedia-page-link{float:left}.rtm-page-number .rtm-go-to-num,.rtm-page-number .rtmedia-page-link{line-height:1.5}.rtm-pagination{background:transparent;border:none;color:#888;font-size:small;margin:0;position:relative;display:block;float:left;width:100%;padding:10px 0}.rtm-pagination .rtm-paginate{float:right;font-size:15px}.rtm-pagination .rtm-paginate a,.rtm-pagination .rtm-paginate span{display:inline-block;line-height:1;margin:0 2px;padding:8px;text-decoration:none}.rtm-pagination .rtm-paginate a.rtmedia-page-link{padding:8px}.rtm-pagination .dashicons{font-size:14px;height:auto;line-height:1.2;margin:0;padding:0;width:auto}#rtmedia_go_to_num{font-size:16px;margin:0 5px;padding:3px 5px;width:80px}.rtmedia-upload-not-allowed{background-color:#fcf8e3;border-bottom:1px solid #EEE;color:#c09853;margin-bottom:20px;padding:10px 15px}.plupload_file_name{position:relative}.plupload_file_name .dashicons{background:#eee;color:#DD3D36;cursor:pointer;font-size:14px;height:auto;padding:0 2px 0 5px;position:absolute;right:0;top:0;width:auto}.plupload_file_name .dashicons-yes{color:#7AD03A}.rtmedia-gallery-item-actions{background-color:rgba(0,0,0,0.6);opacity:0;position:absolute;text-align:center;-webkit-transition:all ease-in-out 0.4s;transition:all ease-in-out 0.4s;width:100%;z-index:9}.rtmedia-gallery-item-actions a{border:0;box-shadow:0 0 0;color:#fff;display:inline-block;font-size:12px;outline:none;padding:4px;text-align:left;text-decoration:none;text-transform:uppercase}.rtmedia-gallery-item-actions .dashicons{font-size:17px;margin-right:2px;position:relative;top:1px}.rtmedia-gallery-item-actions .dashicons-trash{font-size:15px}.rtm-pro-allow-action .rtmedia-list-item:hover .rtmedia-gallery-item-actions{opacity:1}.rtm-pro-allow-action .rtmedia-list-item:hover .rtmedia-bulk-edit-item-wrap+.rtmedia-gallery-item-actions{opacity:0}.rtmedia-footer-link{clear:both;overflow:hidden;padding:16px 0;position:relative;text-align:center}.rtmedia-text-link-decoration,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-edit a,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-edit span,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-delete a,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-delete span,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-title a,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-title span{text-decoration:none}.rtmedia-text-link-decoration:hover,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-edit a:hover,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-edit span:hover,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-delete a:hover,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-delete span:hover,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-title a:hover,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-title span:hover{text-decoration:underline}.rtmedia-container .rtmedia-edit-list-media-table{max-height:300px;overflow-y:auto}.rtmedia-container .rtmedia-edit-list-media-table thead tr{background-color:#50A1D7}.rtmedia-container .rtmedia-edit-list-media-table thead th{text-align:center;color:#FFF}.rtmedia-container .rtmedia-edit-list-media-table tbody tr:nth-child(odd){background:#FFF}.rtmedia-container .rtmedia-edit-list-media-table tbody tr:nth-child(even){background:#DCDCDC}table.rtmedia-edit-media-list tr{line-height:30px}table.rtmedia-edit-media-list tr th{color:#333;padding:4px 10px;line-height:20px}table.rtmedia-edit-media-list tr .rtm-edit-media-list-heading{width:44%}table.rtmedia-edit-media-list tr .rtm-edit-media-list-title-heading{width:56%}table.rtmedia-edit-media-list tr td.rtm-edit-media-list-edit,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-delete,table.rtmedia-edit-media-list tr td.rtm-edit-media-list-title{padding:4px;font-size:14px;line-height:24px}table.rtmedia-edit-media-list tr td.rtm-edit-media-list-title a{text-decoration:none;color:#333}table.rtmedia-edit-media-list tr td.rtm-edit-media-list-edit{text-align:center}table.rtmedia-edit-media-list tr td.rtm-edit-media-list-edit a{color:#333;font-size:13px}table.rtmedia-edit-media-list tr td.rtm-edit-media-list-delete{text-align:center}table.rtmedia-edit-media-list tr td.rtm-edit-media-list-delete span{color:#FF0000;cursor:pointer;font-size:13px}.rtm-hide{display:none}.rtmedia-list-item .rtmedia-album-media-count{position:absolute;top:0;right:0;background-color:black;color:white;padding:0 5px}.rtmedia-actions-before-description>div{margin-bottom:5px}input.imgedit-submit-btn{display:none}.rtmedia-no-media-found,.rtmedia-list-media{min-height:95px}.privacy_message_wrapper{background:rgba(0,0,0,0.95);z-index:999;color:#fff;display:block;position:fixed;width:100%;padding:5px}.privacy_message_wrapper p{margin:20px 25px;width:-webkit-calc( 100% - 100px );width:calc( 100% - 100px );max-width:100%;font-size:85%;text-align:justify;word-wrap:break-word;display:inline-block}.privacy_message_wrapper p a{color:#fff;text-decoration:underline}.privacy_message_wrapper p a:hover{color:#000}.privacy_message_wrapper #close_rtm_privacy_message{margin:0px;float:right;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);position:absolute;display:inline-block;color:inherit;font-size:25px}.privacy_message_wrapper #close_rtm_privacy_message:hover{cursor:pointer}.hide_privacy_wrapper{display:none}.rtm-tabs.rtm-tabs{border-bottom:1px solid #eee;list-style:none;margin:0 0 20px;padding:0}.rtm-tabs li{border:1px solid #eee;border-bottom:0;float:left;margin:0 5px;padding:0}.rtm-tabs a{border:0;display:block;padding:5px 15px;text-decoration:none}.rtm-tabs a:focus{background:transparent;box-shadow:0 0 0}.rtm-tabs .active{position:relative}.rtm-tabs .active:after{background:#fff;bottom:-1px;content:' ';height:1px;left:0;position:absolute;width:100%}.rtm-tabs .dashicons{font-size:16px;height:auto;line-height:20px;margin-right:8px;width:auto}.rtmedia-edit-media-tabs .rtm-tabs a{border-bottom:0 none}.mfp-bg{top:0;left:0;width:100%;height:100%;z-index:104211;overflow:hidden;position:fixed;background:rgba(0,0,0,0.9)}.mfp-wrap{top:0;left:0;width:100%;height:100%;z-index:104311;position:fixed;outline:none !important;-webkit-backface-visibility:hidden}.mfp-container{text-align:center;position:absolute;width:100%;max-width:84%;margin:0 auto;right:0;height:100%;left:0;top:0;padding:0 8px;box-sizing:border-box}.mfp-container:before{content:' ';display:inline-block;height:100%;vertical-align:middle}.mfp-align-top .mfp-container:before{display:none}.mfp-content{position:relative;display:inline-block;vertical-align:middle;margin:0 auto;text-align:left;z-index:1045}.mfp-inline-holder .mfp-content,.mfp-ajax-holder .mfp-content{width:100%;cursor:auto}.mfp-ajax-cur{cursor:progress}.mfp-zoom-out-cur,.mfp-zoom-out-cur .mfp-image-holder .mfp-close{cursor:zoom-out}.mfp-zoom{cursor:pointer;cursor:zoom-in}.mfp-auto-cursor .mfp-content{cursor:auto}.mfp-close,.mfp-arrow,.mfp-preloader,.mfp-counter{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.mfp-loading.mfp-figure{display:none}.mfp-hide{display:none !important}.mfp-s-ready .mfp-preloader{display:none}.mfp-s-error .mfp-content{display:none}button.mfp-close,button.mfp-arrow{overflow:visible;cursor:pointer;background:transparent;border:0;-webkit-appearance:none;display:block;outline:none;padding:0;z-index:1046;box-shadow:none}button::-moz-focus-inner{padding:0;border:0}.mfp-close{background:#fff;color:#999;cursor:pointer;font-size:24px;font-style:normal;height:30px;line-height:30px;padding:0;position:absolute;right:1px;text-align:center;text-decoration:none;text-indent:2px;top:0;width:32px;z-index:12}.mfp-close:hover,.mfp-close:focus{opacity:1;filter:alpha(opacity=100)}.mfp-close:active{top:1px}.mfp-image-holder .mfp-close,.mfp-iframe-holder .mfp-close{color:#FFF;right:-6px;text-align:right;padding-right:6px;width:100%}.mfp-counter{position:absolute;top:0;right:0;color:#CCC;font-size:12px;line-height:18px;white-space:nowrap}.mfp-arrow{cursor:pointer;position:absolute;opacity:0.65;filter:alpha(opacity=65);margin:0;top:50%;margin-top:-55px;padding:0;width:90px;height:110px;-webkit-tap-highlight-color:transparent;opacity:0;z-index:10;-webkit-transition:all 300ms ease-out;transition:all 300ms ease-out}.rtm-single-media:hover .mfp-arrow{opacity:1}@media (max-device-width: 640px){.mfp-arrow{display:none}.rtm-single-media:hover .mfp-arrow{display:none}}.mfp-arrow:active{margin-top:-54px}.mfp-arrow:hover,.mfp-arrow:focus{opacity:1;filter:alpha(opacity=100)}.mfp-arrow:before,.mfp-arrow:after,.mfp-arrow .mfp-b,.mfp-arrow .mfp-a{content:'';display:block;width:0;height:0;position:absolute;left:0;top:0;margin-top:40%;margin-left:40%;border:medium inset transparent}.mfp-arrow:after,.mfp-arrow .mfp-a{border-top-width:13px;border-bottom-width:13px;top:8px}.mfp-arrow:before,.mfp-arrow .mfp-b{border-top-width:21px;border-bottom-width:21px;opacity:0.7}.mfp-arrow-left{left:0}.mfp-arrow-left:after,.mfp-arrow-left .mfp-a{border-right:17px solid #FFF;margin-left:32%}.mfp-arrow-left:before,.mfp-arrow-left .mfp-b{margin-left:25%;border-right:27px solid #3F3F3F}.mfp-arrow-right{right:0}.mfp-arrow-right:after,.mfp-arrow-right .mfp-a{border-left:17px solid #FFF;margin-left:44%}.mfp-arrow-right:before,.mfp-arrow-right .mfp-b{border-left:27px solid #3F3F3F}.mfp-iframe-holder{padding-top:40px;padding-bottom:40px}.mfp-iframe-holder .mfp-content{line-height:0;width:100%;max-width:900px}.mfp-iframe-holder .mfp-close{top:-40px}.mfp-iframe-scaler{width:100%;height:0;overflow:hidden;padding-top:56.25%}.mfp-iframe-scaler iframe{position:absolute;display:block;top:0;left:0;width:100%;height:100%;box-shadow:0 0 8px rgba(0,0,0,0.6);background:#000}img.mfp-img{width:auto;max-width:100%;height:auto;display:block;line-height:0;box-sizing:border-box;padding:40px 0 40px;margin:0 auto}.mfp-figure{line-height:0}.mfp-figure:after{content:'';position:absolute;left:0;top:40px;bottom:40px;display:block;right:0;width:auto;height:auto;z-index:-1;box-shadow:0 0 8px rgba(0,0,0,0.6);background:#444}.mfp-figure small{color:#BDBDBD;display:block;font-size:12px;line-height:14px}.mfp-figure figure{margin:0}.mfp-bottom-bar{margin-top:-36px;position:absolute;top:100%;left:0;width:100%;cursor:auto}.mfp-title{text-align:left;line-height:18px;color:#F3F3F3;word-wrap:break-word;padding-right:36px}.mfp-image-holder .mfp-content{max-width:100%}.mfp-gallery .mfp-image-holder .mfp-figure{cursor:pointer}.mfp-preloader{position:absolute;top:50%;left:0;right:0;margin-top:-36px;z-index:1044;font-size:0;width:36px;height:36px;margin-left:auto;margin-right:auto}.mfp-preloader:before{content:'Loading…';position:absolute;width:30px;height:30px}.mfp-preloader:not(:required):before{content:'';border-radius:50%;border:3px solid rgba(255,255,255,0.27);border-top-color:rgba(255,255,255,0.9);animation:spinner .6s linear infinite;-webkit-animation:spinner .6s linear infinite}@keyframes spinner{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes spinner{to{-webkit-transform:rotate(360deg)}}@media screen and (max-width: 800px) and (orientation: landscape), screen and (max-height: 300px){.mfp-img-mobile .mfp-image-holder{padding-left:0;padding-right:0}.mfp-img-mobile img.mfp-img{padding:0}.mfp-img-mobile .mfp-figure:after{top:0;bottom:0}.mfp-img-mobile .mfp-figure small{display:inline;margin-left:5px}.mfp-img-mobile .mfp-bottom-bar{background:rgba(0,0,0,0.6);bottom:0;margin:0;top:auto;padding:3px 5px;position:fixed;box-sizing:border-box}.mfp-img-mobile .mfp-bottom-bar:empty{padding:0}.mfp-img-mobile .mfp-counter{right:5px;top:3px}.mfp-img-mobile .mfp-close{top:0;right:0;width:35px;height:35px;line-height:35px;background:rgba(0,0,0,0.6);position:fixed;text-align:center;padding:0}}@media all and (max-width: 900px){.mfp-arrow{-webkit-transform:scale(0.75);-ms-transform:scale(0.75);transform:scale(0.75)}.mfp-arrow-left{-webkit-transform-origin:0;-ms-transform-origin:0;transform-origin:0}.mfp-arrow-right{-webkit-transform-origin:100%;-ms-transform-origin:100%;transform-origin:100%}.mfp-container{padding-left:6px;padding-right:6px}}.atwho-container #atwho-ground-comment_content .atwho-view{z-index:2147483647}.mfp-content .rtm-lightbox-container{background:#000;margin:0 auto;position:relative}.mfp-content .rtm-lightbox-container .rtmedia-comment-media-list .mejs-container.mejs-video{min-height:200px;min-width:200px}.mfp-content .rtm-single-meta{background:#fff;overflow:hidden;padding:20px 20px 110px;position:relative;vertical-align:top}.rtm-single-media{overflow:hidden;position:relative;text-align:center;vertical-align:middle}.rtm-single-media .mejs-container{margin:0 auto;max-width:inherit}.rtm-single-media .rtmedia-message-container{position:absolute;top:45%;left:0;right:0;margin-left:auto;margin-right:auto}@media (max-device-width: 640px){.rtm-single-media .rtmedia-message-container{top:25%}}.rtm-ltb-action-container{background-color:rgba(0,0,0,0.6);bottom:0;color:#fff;line-height:38px;opacity:0;padding:0 10px;position:absolute;width:100%;-webkit-transition:all 300ms ease-out;transition:all 300ms ease-out}.rtm-single-media:hover .rtm-ltb-action-container{opacity:1}@media (max-device-width: 640px){.rtm-ltb-action-container{clear:both;position:relative;opacity:1}.rtm-single-media:hover .rtm-ltb-action-container{opacity:1}}#buddypress #rtmedia-single-media-container.rtmedia-single-media .button{background:transparent;border:0 none;border-radius:2px;color:rgba(255,255,255,0.5);display:block;font-family:inherit;font-weight:normal;line-height:24px;margin:0;padding:0 6px;text-shadow:0 0 0;text-transform:none}#buddypress #rtmedia-single-media-container.rtmedia-single-media .button:hover{background:rgba(255,255,255,0.2);color:rgba(255,255,255,0.8)}#buddypress #rtmedia-single-media-container.rtmedia-single-media .rtm-options .button{color:#333;margin:0 auto;padding:0 4px 0 0}#buddypress #rtm-media-options-list .rtm-options .button{background:transparent;border:0 none;border-radius:2px;color:rgba(255,255,255,0.5);float:left;font-family:inherit;font-weight:normal;line-height:24px;padding:0 6px;text-transform:none}#buddypress #rtm-media-options-list .rtm-options .rtmedia-delete-favlist{color:#fff;padding:0}#buddypress #rtm-media-options-list .rtm-options form button{font-size:14px}#buddypress #rtm-media-options-list .rtm-options i{line-height:1.7}.rtm-options.rtm-options{background:#666;color:#fff;display:none;font-size:14px;list-style:none;margin:0;padding:8px 10px;position:absolute;left:0;top:38px;width:190px;z-index:10}.rtm-options li{margin:0;overflow:hidden;padding:2px 0}.rtm-media-options .rtm-options:after{bottom:100%;left:20px;border:solid transparent;content:' ';height:0;width:0;position:absolute;pointer-events:none;border-color:rgba(255,255,255,0);border-bottom-color:#666;border-width:6px;margin-left:-6px}.mfp-content .rtm-options{background:#fff;color:#333;bottom:38px;right:0;left:auto;top:auto}.mfp-content .rtm-options:after{top:100%;right:22px;border:solid transparent;content:' ';height:0;width:0;position:absolute;pointer-events:none;border-color:rgba(255,255,255,0);border-top-color:#fff;border-width:6px;margin-left:-6px}.rtm-options .dashicons{font-size:14px;line-height:24px;margin-right:2px}.rtm-media-options .rtm-options a{border:0;color:#fff;display:block;text-decoration:none}.rtm-ltb-title{color:rgba(255,255,255,0.7);float:left;font-size:13px}.rtm-ltb-title a{color:inherit}.rtm-ltb-title a:hover{border-bottom:1px dotted;color:#fff}.rtm-item-actions{float:right}.rtm-item-actions>div,.rtm-item-actions>form{float:left;margin:0 4px 0 0;padding:7px 0;position:relative}.rtmedia-media{margin:0 auto}.rtmedia-media img{display:inline-block;max-height:inherit;height:auto;max-width:100%;width:auto}@media only screen and (max-device-width: 1024px){.rtmedia-media{margin:40px 0}}.rtm-user-meta-details .username{font-size:16px;line-height:1;margin-bottom:6px}.userprofile{float:left;margin:0 16px 16px 0;max-width:54px}.userprofile a{display:block}.userprofile img{height:auto;max-width:100%}.rtm-time-privacy{color:#999;font-size:12px}.rtm-time-privacy .dashicons{font-size:14px;line-height:1.5;margin-top:-2px}.rtmedia-actions-before-comments>span{float:left;margin-right:10px}.rtmedia-actions-before-comments .rtmedia-comment-link,.rtmedia-actions-before-comments .rtmedia-view-conversation,#buddypress .rtmedia-actions-before-comments .rtmedia-like{border:0;font-size:13px;font-weight:normal;line-height:2;padding:0;text-transform:none}.rtmedia-actions-before-comments .rtmedia-comment-link:hover,.rtmedia-actions-before-comments .rtmedia-view-conversation:hover,#buddypress .rtmedia-actions-before-comments .rtmedia-like:hover{background:transparent}.rtmedia-comment-user-pic{float:left;margin-right:10px;max-width:36px}.rtmedia-comment-user-pic img{height:auto;max-width:100%}.rtm-like-comments-info{position:relative}.rtm-like-comments-info:after{bottom:100%;left:15px;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none;border-color:rgba(237,239,244,0);border-bottom-color:#edeff4;border-width:4px;margin-left:-4px}.rtm-comment-list.rtm-comment-list{height:340px;list-style:none;margin:0;overflow:auto;padding:0}.rtm-comment-list li{background:#edeff4;font-size:12px;margin-bottom:1px;padding:10px;position:relative}.rtm-comment-list li:hover .rtmedia-delete-comment{opacity:1}.rtm-comment-list .rtmedia-no-comments{margin:0;padding:5px 10px}.rtmedia-like-info{background:#edeff4;font-size:12px;margin-bottom:1px;padding:5px 10px;position:relative}.rtm-comment-wrap{overflow:hidden}.rtm-comment-wrap .rtmedia-comment-author{font-weight:700}.rtm-comment-wrap .rtmedia-comment-date{color:#999;font-size:11px}.rtmedia-comment-content{margin-top:2px}.rtmedia-delete-comment{color:#999;cursor:pointer;font-size:16px;opacity:0;position:absolute;right:5px;top:5px}.rtmedia-comment-content p{margin:0}.rtmedia-comment-details{line-height:1.5;margin-top:-3px}.rt_media_comment_form textarea{display:inline-block;margin-bottom:5px}.rtmedia-item-comments textarea{font-size:14px;padding:4px}.rtm-media-single-comments{bottom:20px;padding:10px;width:100%}.rtm-media-single-comments textarea{background-color:#edeff4;font-size:12px;line-height:14px;max-height:40px;min-height:30px;padding:4px}.rtmedia-popup{background:#fff;margin:20px auto;max-width:600px;padding:20px;position:relative;width:auto}.rtmedia-popup .rtm-modal-title{font-size:24px;margin-bottom:20px;margin-top:0}.rtmedia-popup label{display:block;margin-bottom:5px}#rtm-modal-container p{margin-bottom:10px}#rtm-mejs-video-container{margin:0 auto}.rtmedia-media-name{float:left;max-width:140px;overflow:hidden;text-align:left;text-overflow:ellipsis;white-space:nowrap}.rtm-single-media.rtm-media-type-video{padding-bottom:40px;padding-top:40px}.rtmedia-gallery-alert-container{position:fixed;top:0;left:0;height:100%;width:100%;background-color:rgba(0,0,0,0.6);z-index:999997}.rtmedia-gallery-message-box{position:fixed;top:40%;left:50%;margin-left:auto;margin-right:auto;z-index:999999}.rtmedia-gallery-message-box span{position:relative;left:-50%}#mobile-swipe-overlay{position:absolute;display:none;width:100%;height:100%;top:0;left:0;right:0;bottom:0;background-color:rgba(255,255,255,0.7);z-index:15;cursor:pointer}#mobile-swipe-overlay .swipe-icon{position:absolute;top:30%;left:50%;font-size:50px;color:#000;-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%);-ms-transform:translate(-50%, -50%);width:200px}#mobile-swipe-overlay .swipe-icon img{width:100%}#mobile-swipe-overlay .swipe-tootlip{font-weight:800;position:absolute;padding:20px;top:45%;width:100%;text-align:center}.rtmedia-activity-container{box-sizing:border-box}.rtmedia-activity-container *,.rtmedia-activity-container *:before,.rtmedia-activity-container *:after{box-sizing:inherit}.rtmedia-activity-container .rtmedia-list.masonry{list-style:none;padding:0}.rtmedia-activity-container .rtmedia-list.masonry p{display:none}.rtmedia-activity-container .rtmedia-list.masonry:after{content:'';display:block;clear:both}.rtmedia-activity-container .rtmedia-list-item.masonry-brick{display:inline-block;float:left;width:32%;padding:0 !important}.rtmedia-activity-container .rtmedia-list-item.masonry-brick .mejs-container{min-width:33% !important;margin:0 0 5px 0;width:100% !important}.rtmedia-activity-container .rtmedia-list-item.masonry-brick .mejs-container .mejs-controls{width:100%}.rtmedia-activity-container .rtmedia-list-item.masonry-brick .mejs-container .mejs-controls .mejs-time-total{display:none}.rtmedia-activity-container .rtmedia-list-item.masonry-brick .mejs-container .mejs-controls .mejs-horizontal-volume-slider{width:20%;padding-left:5px}.rtmedia-activity-container .rtmedia-list-item.masonry-brick .mejs-container .mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-total{width:100%}.rtmedia-activity-container .rtmedia-list-item.masonry-brick .mejs-container .mejs-controls .mejs-horizontal-volume-slider .mejs-time-loaded{display:none}.rtmedia-activity-container .rtmedia-list-item.masonry-brick img{display:block;max-width:100%}.rtmedia-activity-container .rtmedia-list-item.masonry-brick .rtmedia-item-title{display:none}#buddypress ul.rtmedia-list li{border-bottom:0;padding-bottom:0}.rtmedia-activity-container .rtmedia-item-actions{display:none}.rtmedia-activity-container .rtmedia-item-title,.rtmedia-activity-container .rtmedia-item-title a{border:0;color:#666;font-size:13px;margin:5px 0 0;overflow:hidden;text-align:center;text-overflow:ellipsis;white-space:nowrap}#rtmedia-whts-new-upload-container div{left:0 !important;position:absolute;top:0 !important}#aw-whats-new-submit,.rtmedia-add-media-button{display:block}.rtm-drag-drop-active{border:4px dashed green !important;display:block;height:100%;opacity:0.5;z-index:9999}#rtm-drop-files-title{background:rgba(0,0,0,0.2);display:none;font-size:14px;height:100%;padding:20px;position:absolute;top:0;width:100%}#rtSelectPrivacy{float:right}form.rt_media_comment_form .rtmedia-plupload-container{overflow:hidden}.rtmedia-plupload-container{position:relative;float:left}.rtm-upload-button-wrapper{float:left;margin-right:5px}#rtmedia-action-update{margin-right:10px}.rtmedia-list-item.media-type-photo,.rtmedia-list-item.media-type-document,.rtmedia-list-item.media-type-music,.rtmedia-list-item.media-type-video{display:inline-block}.media-type-music .mejs-container{margin-bottom:10px}.previous-pagination{float:left;margin-top:10px}.next-pagination{float:right;margin-top:10px}@media screen and (max-width: 500px){#activity-stream li .media-type-video{width:100%}#activity-stream li .media-type-video .mejs-video{max-width:100%;min-width:100%}}#rtmedia_show_all_comment{cursor:pointer}#rtmedia_show_all_comment:hover{text-decoration:underline}#whats-new-options{opacity:0;display:none}#whats-new-options .rtmedia-uploader-div{opacity:0;display:none;visibility:hidden}.bp-nouveau .activity-update-form .rtmedia-uploader-div{margin-left:8.5%}.bp-nouveau .activity-update-form .rtmedia-plupload-container{width:25%}.bp-nouveau .activity-update-form .rtmedia-upload-terms #rtmedia_upload_terms_conditions{margin-left:20px}.bp-nouveau .activity-update-form #aw-whats-new-submit{margin-top:15px}.ac-form .rtmedia-uploader-div,.rt_media_comment_form .rtmedia-uploader-div{opacity:1;display:block;visibility:visible}#whats-new-options{opacity:0;display:none}a.rtmedia-comment-link{display:none}a.rtmedia-comment-link.rtmedia-comments-link{display:initial}.rtmedia-album-edit .rtm-checkbox-wrap{background:rgba(255,255,255,0.9);height:30px;line-height:1;padding:10px;position:absolute;z-index:10}.rtmedia-album-edit .rtmedia-item-selector{position:relative;top:-7px}.rtmedia-album-edit .rtmedia-move-container{display:none}.rtm-single-actions.rtm-item-actions{float:none}.rtm-media-type-music .rtmedia-media{width:100%}.media-item .describe{border-collapse:collapse;width:100%;border-top-style:solid;border-top-width:1px;clear:both;cursor:default}.media-item.media-blank .describe{border:0}.media-item .describe th{vertical-align:top;text-align:left;padding:5px 10px 10px;width:140px}.media-item .describe .align th{padding-top:0}.media-item .media-item-info tr{background-color:transparent}.media-item .describe td{padding:0 8px 8px 0;vertical-align:top}.media-item thead.media-item-info td{padding:4px 10px 0}.media-item .media-item-info .A1B1{padding:0 0 0 10px}.media-item td.savesend{padding-bottom:15px}.media-item .thumbnail{max-height:128px;max-width:128px}#wpbody-content #async-upload-wrap a{display:none}.media-upload-form{margin-top:20px}.media-upload-form td label{margin-right:6px;margin-left:2px}.media-upload-form .align .field label{display:inline;padding:0 0 0 23px;margin:0 1em 0 3px;font-weight:bold}.media-upload-form tr.image-size label{margin:0 0 0 5px;font-weight:bold}.media-upload-form th.label label{font-weight:bold;margin:0.5em;font-size:13px}.media-upload-form th.label label span{padding:0 5px}abbr.required{border:medium none;text-decoration:none}.media-item .describe input[type="text"],.media-item .describe textarea{width:460px}.media-item .describe p.help{margin:0;padding:0 0 0 5px}.media-item .edit-attachment,.describe-toggle-on,.describe-toggle-off{display:block;line-height:36px;float:right;margin-right:15px}.media-item .describe-toggle-off,.media-item.open .describe-toggle-on{display:none}.media-item.open .describe-toggle-off{display:block}#media-items .media-item{border-style:solid;border-width:1px;min-height:36px;position:relative;margin-top:-1px;width:100%}#media-items{width:623px}.media-new-php #media-items{margin:1em 0}#media-items:empty{border:0 none}.media-item .filename{line-height:36px;overflow:hidden;padding:0 10px}.media-item .error-div{padding-left:10px}.media-item .pinkynail{float:left;margin:2px 2px 0;max-width:40px;max-height:32px}.media-item .startopen,.media-item .startclosed{display:none}.media-item .original{position:relative;height:34px}.media-item .progress{float:right;height:22px;margin:6px 10px 0 0;width:200px;line-height:2em;padding:0;overflow:hidden;margin-bottom:2px;border:1px solid #d1d1d1;background:#f7f7f7;background-image:-webkit-gradient(linear, left bottom, left top, from(#fff), to(#f7f7f7));background-image:-webkit-linear-gradient(bottom, #fff, #f7f7f7);background-image:linear-gradient(to top, #fff, #f7f7f7);border-radius:3px;box-shadow:inset 0 0 3px rgba(0,0,0,0.1)}.media-item .bar{z-index:9;width:0;height:100%;margin-top:-24px;background-color:#8cc1e9;background-image:-webkit-gradient(linear, left bottom, left top, from(#72a7cf), to(#8cc1e9));background-image:-webkit-linear-gradient(bottom, #72a7cf, #8cc1e9);background-image:linear-gradient(to top, #72a7cf, #8cc1e9);border-radius:3px;box-shadow:0 0 3px rgba(0,0,0,0.3)}.media-item .progress .percent{z-index:10;position:relative;width:200px;padding:0 8px;text-shadow:0 1px 0 rgba(255,255,255,0.4);color:rgba(0,0,0,0.6)}.upload-php .fixed .column-parent{width:15%}.js .html-uploader #plupload-upload-ui{display:none}.js .html-uploader #html-upload-ui{display:block}.media-upload-form .media-item.error{margin:0;padding:0}.media-upload-form .media-item.error p,.media-item .error-div{line-height:16px;margin:5px 10px;padding:0}.media-item .error-div a.dismiss{display:block;float:right;margin:5px 4px 0 15px}.find-box{width:600px;height:300px;overflow:hidden;padding:33px 0 51px;position:absolute;z-index:1000}.find-box-head{cursor:move;font-weight:bold;height:2em;line-height:2em;padding:1px 12px;position:absolute;top:5px;width:100%}.find-box-inside{overflow:auto;padding:6px;height:100%}.find-box-search{overflow:hidden;padding:9px;position:relative}.find-box-search .spinner{float:none;left:125px;position:absolute;top:9px}#find-posts-input{float:left;width:140px;height:24px}#find-posts-search{float:left;margin:1px 4px 0 3px}#find-posts-response{margin:8px 0;padding:0 1px 6px}#find-posts-response table{width:100%}#find-posts-response .found-radio{padding:3px 0 0 8px;width:15px}.find-box-buttons{padding:8px;overflow:hidden}.find-box #resize-se{position:absolute;right:1px;bottom:1px}.ui-find-overlay{position:absolute;top:0;left:0;background-color:#000;opacity:0.6;filter:alpha(opacity=60)}ul#dismissed-updates{display:none}form.upgrade{margin-top:8px}form.upgrade .hint{font-style:italic;font-size:85%;margin:-0.5em 0 2em 0}#poststuff .inside .the-tagcloud{margin:5px 0 10px;padding:8px;border-width:1px;border-style:solid;line-height:1.8em;word-spacing:3px;border-radius:6px}.drag-drop #drag-drop-area{border:4px dashed #DDDDDD;height:200px}.drag-drop .drag-drop-inside{margin:70px auto 0;width:250px}.drag-drop-inside p{color:#aaa;font-size:14px;margin:5px 0;display:none}.drag-drop .drag-drop-inside p{text-align:center}.drag-drop-inside p.drag-drop-info{font-size:20px}.drag-drop .drag-drop-inside p,.drag-drop-inside p.drag-drop-buttons{display:block}.drag-drop.drag-over #drag-drop-area{border-color:#83b4d8}#plupload-upload-ui{position:relative}.describe .image-editor{vertical-align:top}.imgedit-wrap{position:relative}#item-body .imgedit-settings .imgedit-group-top h2{display:inline-block;margin:0}.rtmedia-container .rtmedia-image-editor-cotnainer label{display:inline-block;float:none;margin-right:0}.rtmedia-container .rtmedia-image-editor-cotnainer .dashicons-editor-help{padding:0;height:auto;margin-top:10px}.rtmedia-container .rtmedia-image-editor-cotnainer .hidden{display:none}.imgedit-settings p{margin:8px 0}.post-php .imgedit-wrap table{width:100%}.describe .imgedit-wrap table td,.wp_attachment_holder .imgedit-wrap table td{vertical-align:top;padding-top:0}.describe .imgedit-wrap table td.imgedit-settings{padding:0 5px}.wp_attachment_holder .imgedit-wrap table td.imgedit-settings{width:250px}td.imgedit-settings input{margin-top:0;vertical-align:middle}.imgedit-wait{position:absolute;top:0;background:#fff url(../../../../../../wp-admin/images/wpspin_light.gif) no-repeat scroll 22px 10px;background-size:16px 16px;opacity:0.7;filter:alpha(opacity=70);width:100%;height:500px;display:none}.spinner{background:url(../../../../../../wp-admin/images/wpspin_light.gif) no-repeat;background-size:16px 16px;display:none;float:right;opacity:0.7;filter:alpha(opacity=70);width:16px;height:16px;margin:5px 5px 0}.no-float{float:none}.media-disabled,.imgedit-settings .disabled{color:grey}.wp_attachment_image,.A1B1{overflow:hidden}.wp_attachment_image .button,.A1B1 .button{float:left}.no-js .wp_attachment_image .button{display:none}.wp_attachment_image .spinner,.A1B1 .spinner{float:left;padding:0 4px 4px;vertical-align:bottom}.imgedit-menu{margin:0 0 12px;min-width:300px}.imgedit-menu div{float:left;width:32px;height:32px}.imgedit-crop-wrap{position:relative}.imgedit-crop{margin:0 8px 0 0}.imgedit-crop.disabled:hover{background-position:-9px -31px}.imgedit-crop:hover{background-position:-9px -1px}.imgedit-rleft{margin:0 3px}.imgedit-rleft.disabled:hover{background-position:-46px -31px}.imgedit-rleft:hover{background-position:-46px -1px}.imgedit-rright{margin:0 8px 0 3px}.imgedit-rright.disabled:hover{background-position:-77px -31px}.imgedit-rright:hover{background-position:-77px -1px}.imgedit-flipv{margin:0 3px}.imgedit-flipv.disabled:hover{background-position:-115px -31px}.imgedit-flipv:hover{background-position:-115px -1px}.imgedit-fliph{margin:0 8px 0 3px}.imgedit-fliph.disabled:hover{background-position:-147px -31px}.imgedit-fliph:hover{background-position:-147px -1px}.imgedit-undo{margin:0 3px}.imgedit-undo.disabled:hover{background-position:-184px -31px}.imgedit-undo:hover{background-position:-184px -1px}.imgedit-redo{margin:0 8px 0 3px}.imgedit-redo.disabled:hover{background-position:-215px -31px}.imgedit-redo:hover{background-position:-215px -1px}.imgedit-applyto img{margin:0 8px 0 0}.imgedit-group h3{font-size:18px}.imgedit-group .dashicons{border:0;line-height:1.2}.imgedit-group-top{margin:5px 0}.imgedit-applyto .imgedit-label{padding:2px 0 0;display:block}.imgedit-help{display:none;font-style:italic;margin-bottom:8px}a.imgedit-help-toggle{text-decoration:none}.form-table td.imgedit-response{padding:0}.imgedit-submit{margin:8px 0}.imgedit-submit-btn{margin-left:20px}.imgedit-wrap .nowrap{white-space:nowrap}span.imgedit-scale-warn{color:red;font-size:20px;font-style:normal;visibility:hidden;vertical-align:middle}.wp_attachment_details{margin-bottom:20px}.imgedit-menu div{border-color:#d5d5d5;background-color:#f1f1f1}.imgedit-menu div:hover{border-color:#c1c1c1;background-color:#eaeaea}.imgedit-menu div.disabled{border-color:#ccc;background-color:#ddd;filter:alpha(opacity=50);opacity:0.5}.bp-media-image-editor-cotnainer{margin-top:35px}.wp_attachment_image .bp-media-image-edit{float:left}.wp_attachment_image .spinner{display:none}.bp-media-image-editor-cotnainer .hidden{display:none}.bp-media-image-editor-cotnainer div.updated{margin:5px 0 15px;background-color:#ffffe0;border-color:#e6db55;padding:0 .6em;border-radius:3px;border-width:1px;border-style:solid}.bp-media-image-editor-cotnainer div.updated p{margin:.5em 0;padding:2px}body article.bp_members.bp_member .entry-content,body div.bp_members.bp_member .entry-content{width:100%}.rtm-media-gallery-uploader{display:none}h2.rtm-gallery-title{margin:10px 0}.rtmedia-uploader .drag-drop{border:4px dashed #DDD;text-align:center;background:#fafafa;overflow:hidden;color:#AAAAAA;margin-top:20px;padding:25px 0}.rtmedia-uploader .drag-drop.dragover{border-color:#83b4d8}.rtmedia-uploader .drag-drop .drag-drop-info{font-size:20px;line-height:24px}.rtmedia-uploader .drag-drop .rtm-select-files span{vertical-align:middle}.rtmedia-uploader .drag-drop .rtm-seperator{margin:0px 20px}.rtmedia-uploader .drag-drop .start-media-upload{display:none;margin-top:20px}.rtmedia-uploader .drag-drop .rtm-file-size-limit{vertical-align:middle;font-size:16px;line-height:24px}.rtm-uploader-main-wrapper .rtm-uploader-tabs{margin-bottom:10px;text-align:left}.rtm-uploader-main-wrapper ul{border-bottom:1px solid #CCC}.rtm-uploader-main-wrapper li{margin:0 0 -1px 10px;display:inline-block;padding:5px 10px;line-height:25px;background-color:#e4e4e4;border:1px solid #CCC}.rtm-uploader-main-wrapper li.active{background:transparent;border-left:1px solid #CCC;border-top:1px solid #CCC;border-right:1px solid #CCC;border-bottom:1px solid #fafafa}.rtm-uploader-main-wrapper li:hover{cursor:pointer}.rtmedia-container .rtmedia-list{margin:10px -5px}.rtmedia-container .rtmedia-list .rtmedia-list-item{float:left;margin:5px;position:relative}.rtmedia-container .rtmedia-list .rtmedia-list-item>a{display:block}.rtmedia-container .rtmedia-list .rtmedia_time{background-color:#000;color:#fff;display:inline-block;font-size:11px;font-weight:bold;line-height:14px;opacity:0.75;padding:0 4px;position:absolute;right:2px;top:2px}.rtmedia-container .rtmedia-list img{vertical-align:top}.rtmedia-container .rtmedia-list .rtmedia-item-title h4{color:#666;font-size:12px;font-weight:normal;margin:5px 0 0;overflow:hidden;text-align:center;text-overflow:ellipsis;white-space:nowrap}.rtm-load-more{background:#eee;text-align:center}.rtmedia-container .rtm-load-more a{border:0;padding:10px 0}.rtm-load-more .rtm-media-loading{padding:10px 0}.rtm-media-options.rtm-media-search-enable>*:nth-last-child(2){border-right:none}.rtm-media-options{line-height:1.4;margin-bottom:10px;clear:both}.rtm-media-options>div{display:inline-block;cursor:pointer}.rtm-media-options .rtm-media-options-list{margin-right:5px;padding-right:10px;position:relative}.rtm-media-options>*{border-right:1px solid #999}.rtm-media-options>*:last-child{border-right:none}.rtm-media-options .dashicons{font-size:inherit;line-height:1.4}#buddypress .media_search.media_search .search_by{margin-top:3px}.bp-legacy.media #buddypress #item-header-cover-image .user-nicename{margin-bottom:20px}.bp-legacy.media #buddypress div#item-header div#item-header-content ul li,.bp-legacy.media #buddypress div#item-header div#item-header-content ul div{float:left;margin:2px 10px}.bp-legacy.media #buddypress div#item-header div#item-header-content button,.bp-legacy.media #buddypress div#item-header div#item-header-content a{background:#fff;border:1px solid #ccc;color:#767676;font-size:small;cursor:pointer;outline:none;padding:4px 10px;text-align:center;text-decoration:none}.bp-legacy.media #buddypress div#item-header div#item-header-content button:hover,.bp-legacy.media #buddypress div#item-header div#item-header-content a:hover{background:#ededed;border:1px solid #bbb;color:#555;outline:none}.bp-nouveau.media .entry-title{font-size:34px;font-weight:inherit;margin-bottom:0}.bp-nouveau.media .entry-title a{color:#767676}.bp-nouveau.media #buddypress #item-header-cover-image .user-nicename{margin-top:15px;margin-bottom:30px}.bp-nouveau.media #buddypress div#item-header div#item-header-content ul li,.bp-nouveau.media #buddypress div#item-header div#item-header-content ul div{float:left;margin:2px 10px}.bp-nouveau.media #buddypress div#item-header div#item-header-content button,.bp-nouveau.media #buddypress div#item-header div#item-header-content a{background:#fff;border-color:#ccc;border-style:solid;border-width:1px;color:#555;cursor:pointer;font-size:inherit;font-weight:400;outline:none;padding:0.3em 0.5em;text-align:center;text-decoration:none;width:auto}.bp-nouveau.media #buddypress div#item-header div#item-header-content button:hover,.bp-nouveau.media #buddypress div#item-header div#item-header-content a:hover{background:#ededed;border-color:#999999;color:#333;outline:none;text-decoration:none}.media_search.media_search{float:right;border:1px solid #ccc;margin-left:5px;padding:3px 0}.media_search.media_search .media_search_input{width:200px;outline:0;max-width:200px;margin:0;box-shadow:none;padding:5px 6px;border:none;background:transparent;float:left;max-height:30px}.media_search.media_search #media_fatch_loader.load{float:left;width:20px;height:30px;position:relative}.media_search.media_search #media_fatch_loader.load:before{content:'';border-radius:50%;border:1px solid #aaa;border-top-color:rgba(255,255,255,0.9);animation:spinner .8s linear infinite;-webkit-animation:spinner .8s linear infinite;position:absolute;width:15px;height:15px;top:24%}.media_search.media_search .search_option{padding:0;background:transparent;color:#000;margin-bottom:0;line-height:1;border:none}.media_search.media_search .media_search_remove.search_option{display:none}.media_search.media_search .media_search_remove.search_option i{margin-top:4px}.media_search.media_search .search_by{background:transparent;margin-top:3px;float:left;width:auto;margin-bottom:0;height:auto;padding-top:0;padding-bottom:0}@keyframes spinner{to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes spinner{to{-webkit-transform:rotate(360deg)}}.rtmedia-upload-media-link{cursor:pointer}a.rtmedia-upload-media-link{border:none}.rtm-album-privacy span{font-size:16px;display:inline-block;margin:0 20px 20px 20px;vertical-align:top}.rtm-album-privacy label{margin-right:8px}.rtm-album-privacy .dashicons{font-size:16px;line-height:1.6;margin-right:5px}#rtm-media-options-list .rtmedia-delete-album{background:transparent;border:0;color:#fff;font-family:inherit;font-size:inherit;font-weight:inherit;padding:0;text-transform:inherit}#rtm-media-options-list .rtmedia-delete-album:hover{background:transparent;border:0;color:#fff}.rtmedia-single-container button.rtmedia-like{background-color:transparent;color:inherit}#buddypress #item-body{padding:0 20px}#buddypress .mejs-controls button{padding:4px 8px;border:none;background:transparent url("../../../lib/media-element/mejs-controls.png") no-repeat}#buddypress .mejs-controls .mejs-play>button{background-position:0 0}#buddypress .mejs-controls .mejs-pause>button{background-position:-20px 0}#buddypress .mejs-controls .mejs-unmute>button{background-position:-40px 0}#buddypress .mejs-controls .mejs-mute>button{background-position:-60px 0}#buddypress .mejs-controls .mejs-fullscreen-button>button{background-position:-80px 0}#buddypress .mejs-controls .mejs-unfullscreen>button{background-position:-100px 0}#buddypress .mejs-controls .mejs-replay>button{background-position:-160px 0}.mejs-container .mejs-controls .mejs-time{padding:15px 3px 0;content:''}.rtmedia-activity-container .mejs-playpause-button.mejs-play button:before,.rtmedia-activity-container .mejs-playpause-button.mejs-pause button:before,.rtmedia-activity-container .mejs-volume-button.mejs-mute button:before,.rtmedia-activity-container .mejs-fullscreen-button button:before,.rtmedia-media .mejs-playpause-button.mejs-play button:before,.rtmedia-media .mejs-playpause-button.mejs-pause button:before,.rtmedia-media .mejs-volume-button.mejs-mute button:before,.rtmedia-media .mejs-fullscreen-button button:before{content:''}@media only screen and (min-width: 1025px){.mfp-content .rtm-lightbox-container{display:-webkit-box;display:-ms-flexbox;display:flex;table-layout:fixed;width:100%;min-height:473px}.mfp-content .rtm-mfp-close{background:transparent}.mfp-content .rtm-single-media{display:-webkit-box;display:-ms-flexbox;display:flex;width:66.6667%;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.mfp-content .rtm-single-meta{display:block;width:33.3333%;padding:20px}.mfp-content .rtm-single-meta .rtmedia-scroll{height:100%;overflow-X:hidden}}.rtl #rtSelectPrivacy{float:left}.rtl .rtmedia-plupload-container{float:right}.rtl .rtm-upload-button-wrapper{float:right}.rtl #whats-new-post-in-box{float:right}.rtl .describe-toggle-off{float:left}.rtl .media-item .pinkynail{float:right}.rtl .media-item .progress{float:left}.rtl .media-item .error-div a.dismiss{float:left}.rtl #find-posts-input{float:right}.rtl #find-posts-search{float:right}.rtl .spinner{float:left}.rtl .wp_attachment_image .button,.rtl .A1B1 .button{float:right}.rtl .wp_attachment_image .spinner,.rtl .A1B1 .spinner{float:right}.rtl .imgedit-menu div{float:right}.rtl .wp_attachment_image .bp-media-image-edit{float:right}.rtl .rtmedia-container .rtmedia-list .rtmedia-list-item{float:right}.rtl #buddypress #rtm-media-options-list .rtm-options .button{float:right}.rtl .rtm-ltb-title{float:right}.rtl .rtm-item-actions{float:left}.rtl .rtm-item-actions>div,.rtl .rtm-item-actions>form{float:right}.rtl .userprofile{float:right}.rtl .rtmedia-actions-before-comments>span{float:right}.rtl .rtmedia-comment-user-pic{float:right}.rtl .rtmedia-media-name{float:right}.rtl #rtmedia-uploader-form .rtm-plupload-list li,.rtl #rtmedia_uploader_filelist li{float:right}.rtl .rtm-page-number{float:right}.rtl .rtm-page-number .rtmedia-page-link{float:right}.rtl .rtm-pagination{float:right}.rtl .rtm-pagination .rtm-paginate{float:left}.rtl .rtm-tabs li{float:right}.rtl .alignleft{float:right}.rtl .alignright{float:left}
|
app/assets/css/sass/_media-tab.scss
CHANGED
@@ -11,6 +11,10 @@ body {
|
|
11 |
display: none;
|
12 |
}
|
13 |
|
|
|
|
|
|
|
|
|
14 |
.rtmedia-uploader {
|
15 |
.drag-drop {
|
16 |
border: 4px dashed #DDD;
|
11 |
display: none;
|
12 |
}
|
13 |
|
14 |
+
h2.rtm-gallery-title {
|
15 |
+
margin: 10px 0;
|
16 |
+
}
|
17 |
+
|
18 |
.rtmedia-uploader {
|
19 |
.drag-drop {
|
20 |
border: 4px dashed #DDD;
|
app/assets/css/sass/_popup.scss
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
/*
|
2 |
* popup autocomplete
|
3 |
*/
|
4 |
-
|
5 |
#atwho-ground-comment_content {
|
6 |
.atwho-view {
|
7 |
z-index: 2147483647;
|
@@ -124,14 +124,6 @@
|
|
124 |
}
|
125 |
}
|
126 |
|
127 |
-
#buddypress #rtm-media-options-list {
|
128 |
-
.rtm-options {
|
129 |
-
form button {
|
130 |
-
font-size: small;
|
131 |
-
}
|
132 |
-
}
|
133 |
-
}
|
134 |
-
|
135 |
#buddypress #rtm-media-options-list {
|
136 |
.rtm-options {
|
137 |
.button {
|
@@ -144,7 +136,6 @@
|
|
144 |
font-weight: normal;
|
145 |
line-height: 24px;
|
146 |
padding: 0 6px;
|
147 |
-
text-shadow: 0 0 0;
|
148 |
text-transform: none;
|
149 |
}
|
150 |
|
@@ -152,6 +143,14 @@
|
|
152 |
color: $white;
|
153 |
padding: 0;
|
154 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
155 |
}
|
156 |
}
|
157 |
|
1 |
/*
|
2 |
* popup autocomplete
|
3 |
*/
|
4 |
+
.atwho-container {
|
5 |
#atwho-ground-comment_content {
|
6 |
.atwho-view {
|
7 |
z-index: 2147483647;
|
124 |
}
|
125 |
}
|
126 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
127 |
#buddypress #rtm-media-options-list {
|
128 |
.rtm-options {
|
129 |
.button {
|
136 |
font-weight: normal;
|
137 |
line-height: 24px;
|
138 |
padding: 0 6px;
|
|
|
139 |
text-transform: none;
|
140 |
}
|
141 |
|
143 |
color: $white;
|
144 |
padding: 0;
|
145 |
}
|
146 |
+
|
147 |
+
form button {
|
148 |
+
font-size: 14px;
|
149 |
+
}
|
150 |
+
|
151 |
+
i {
|
152 |
+
line-height: 1.7;
|
153 |
+
}
|
154 |
}
|
155 |
}
|
156 |
|
app/assets/css/sass/_rtm.scss
CHANGED
@@ -200,9 +200,14 @@ button#rtmedia-add-media-button-post-update {
|
|
200 |
}
|
201 |
|
202 |
#buddypress {
|
203 |
-
|
204 |
-
|
|
|
|
|
|
|
|
|
205 |
}
|
|
|
206 |
}
|
207 |
|
208 |
// Pagination
|
@@ -222,6 +227,10 @@ button#rtmedia-add-media-button-post-update {
|
|
222 |
.rtmedia-page-link {
|
223 |
float: left;
|
224 |
}
|
|
|
|
|
|
|
|
|
225 |
}
|
226 |
|
227 |
.rtm-pagination {
|
@@ -264,12 +273,13 @@ button#rtmedia-add-media-button-post-update {
|
|
264 |
padding: 0;
|
265 |
width: auto;
|
266 |
}
|
|
|
267 |
}
|
268 |
|
269 |
#rtmedia_go_to_num {
|
270 |
font-size: 16px;
|
271 |
margin: 0 5px;
|
272 |
-
padding:
|
273 |
width: 80px;
|
274 |
}
|
275 |
|
200 |
}
|
201 |
|
202 |
#buddypress {
|
203 |
+
a.rtm-button-back{
|
204 |
+
padding: 3px 10px;
|
205 |
+
}
|
206 |
+
div.rtmedia-page-no.rtm-page-number {
|
207 |
+
a.rtmedia-page-link.button {
|
208 |
+
padding: 5px 10px;
|
209 |
}
|
210 |
+
}
|
211 |
}
|
212 |
|
213 |
// Pagination
|
227 |
.rtmedia-page-link {
|
228 |
float: left;
|
229 |
}
|
230 |
+
.rtm-go-to-num,
|
231 |
+
.rtmedia-page-link {
|
232 |
+
line-height: 1.5;
|
233 |
+
}
|
234 |
}
|
235 |
|
236 |
.rtm-pagination {
|
273 |
padding: 0;
|
274 |
width: auto;
|
275 |
}
|
276 |
+
|
277 |
}
|
278 |
|
279 |
#rtmedia_go_to_num {
|
280 |
font-size: 16px;
|
281 |
margin: 0 5px;
|
282 |
+
padding: 3px 5px;
|
283 |
width: 80px;
|
284 |
}
|
285 |
|
app/assets/js/rtMedia.backbone.js
CHANGED
@@ -684,7 +684,7 @@ jQuery( function( $ ) {
|
|
684 |
|
685 |
// Show/create text box to edit media title
|
686 |
if ( jQuery( rtm_file_title_input ).length === 0 ) {
|
687 |
-
jQuery( rtm_file_label ).parent( '.plupload_file_name' ).prepend( '<div id="' + rtm_file_title_wrapper_id + '" class="rtm-upload-edit-title-wrapper"><label>' + rtmedia_edit_media_info_upload.title + '</label><input type="text" class="rtm-upload-edit-title" id="' + rtm_file_title_id + '" value="' + file.title + '" style="width: 75%;" /></div><div id="' + rtm_file_desc_wrapper_id + '" class="rtm-upload-edit-desc-wrapper"><label>' + rtmedia_edit_media_info_upload.description + '</label><textarea class="rtm-upload-edit-desc" id="' + rtm_file_desc_id + '"></textarea></div><span id="' + rtm_file_save_id + '" title="Save Change" class="
|
688 |
} else {
|
689 |
jQuery( rtm_file_title_wrapper ).show();
|
690 |
jQuery( rtm_file_desc_wrapper ).show();
|
@@ -879,7 +879,7 @@ jQuery( function( $ ) {
|
|
879 |
activity_id = rtnObj.activity_id;
|
880 |
if ( rtnObj.permalink != '' ) {
|
881 |
$( "#" + file.id + " .plupload_file_name" ).html( "<a href='" + rtnObj.permalink + "' target='_blank' title='" + rtnObj.permalink + "'>" + file.title.substring( 0, 40 ).replace( /(<([^>]+)>)/ig, "" ) + "</a>" );
|
882 |
-
$( "#" + file.id + " .plupload_media_edit" ).html( "<a href='" + rtnObj.permalink + "edit' target='_blank'><span title='" + rtmedia_edit_media + "'><i class='dashicons dashicons-edit
|
883 |
$( "#" + file.id + " .plupload_delete" ).html( "<span id='" + rtnObj.media_id + "' class='rtmedia-delete-uploaded-media dashicons dashicons-dismiss' title='" + rtmedia_delete + "'></span>" );
|
884 |
}
|
885 |
|
@@ -1227,7 +1227,7 @@ jQuery( document ).ready( function( $ ) {
|
|
1227 |
|
1228 |
// Show/create text box to edit media title
|
1229 |
if ( jQuery( rtm_file_title_input ).length === 0 ) {
|
1230 |
-
jQuery( rtm_file_label ).parent( '.plupload_file_name' ).prepend( '<div id="' + rtm_file_title_wrapper_id + '" class="rtm-upload-edit-title-wrapper"><label>' + rtmedia_edit_media_info_upload.title + '</label><input type="text" class="rtm-upload-edit-title" id="' + rtm_file_title_id + '" value="' + file.title + '" style="width: 75%;" /></div><div id="' + rtm_file_desc_wrapper_id + '" class="rtm-upload-edit-desc-wrapper"><label>' + rtmedia_edit_media_info_upload.description + '</label><textarea class="rtm-upload-edit-desc" id="' + rtm_file_desc_id + '"></textarea></div><span id="' + rtm_file_save_id + '" title="Save Change" class="
|
1231 |
} else {
|
1232 |
jQuery( rtm_file_title_wrapper ).show();
|
1233 |
jQuery( rtm_file_desc_wrapper ).show();
|
@@ -1292,10 +1292,12 @@ jQuery( document ).ready( function( $ ) {
|
|
1292 |
* if user want media and activity_text both require
|
1293 |
* By: Yahil
|
1294 |
*/
|
1295 |
-
if (
|
1296 |
-
if ( rtmedia_activity_text_with_attachment == 'disable') {
|
1297 |
-
|
1298 |
-
|
|
|
|
|
1299 |
} else {
|
1300 |
jQuery('#whats-new-form').prepend('<div id="message" class="error bp-ajax-message" style="display: block;"><p> ' + rtmedia_empty_activity_msg + ' </p></div>')
|
1301 |
jQuery( '#whats-new' ).removeAttr( 'disabled' );
|
@@ -1392,11 +1394,15 @@ jQuery( document ).ready( function( $ ) {
|
|
1392 |
}
|
1393 |
} );
|
1394 |
|
1395 |
-
var object
|
1396 |
-
var item_id =
|
1397 |
-
|
1398 |
-
|
1399 |
-
|
|
|
|
|
|
|
|
|
1400 |
if ( item_id > 0 ) {
|
1401 |
object = 'group';
|
1402 |
} else {
|
@@ -1687,10 +1693,10 @@ jQuery( document ).ready( function( $ ) {
|
|
1687 |
|
1688 |
|
1689 |
$( this ).attr( 'disabled', 'disabled' );
|
1690 |
-
|
1691 |
-
|
1692 |
-
|
1693 |
-
|
1694 |
$.ajax( {
|
1695 |
url: comment_form_el.attr( 'action' ),
|
1696 |
type: 'post',
|
@@ -1783,6 +1789,7 @@ jQuery( document ).ready( function( $ ) {
|
|
1783 |
}
|
1784 |
|
1785 |
$( '.rtmedia-like span' ).html( data.next );
|
|
|
1786 |
$( '.rtmedia-like-counter-wrap' ).html( data.person_text );
|
1787 |
$( '.rtm-like-loading' ).remove();
|
1788 |
$( that ).removeAttr( 'disabled' );
|
@@ -1888,15 +1895,15 @@ function rtmedia_selected_file_list( plupload, file, uploader, error, comment_me
|
|
1888 |
if ( error == '' ) {
|
1889 |
upload_progress = '<div class="plupload_file_progress ui-widget-header" style="width: 0%;">';
|
1890 |
upload_progress += '</div>';
|
1891 |
-
icon = '<span id="label_' + file.id + '" class="dashicons dashicons-edit
|
1892 |
} else if ( error.code == -600 ) {
|
1893 |
err_msg = ( uploader != '' ) ? rtmedia_max_file_msg + uploader.settings.max_file_size : window.file_size_info;
|
1894 |
title = 'title=\'' + err_msg + '\'';
|
1895 |
-
icon = '<i class="dashicons dashicons-info
|
1896 |
} else if ( error.code == -601 ) {
|
1897 |
err_msg = error.message + '. ' + window.file_extn_info;
|
1898 |
title = 'title=\'' + err_msg + '\'';
|
1899 |
-
icon = '<i class="dashicons dashicons-info
|
1900 |
}
|
1901 |
|
1902 |
var rtmedia_plupload_file = '<li class="plupload_file ui-state-default plupload_queue_li" id="' + file.id + '" ' + title + '>';
|
@@ -2407,6 +2414,7 @@ function renderUploadercomment_media( widget_id, parent_id_type ) {
|
|
2407 |
jQuery( input_file_el ).click();
|
2408 |
file_dialog_open = false;
|
2409 |
}
|
|
|
2410 |
} );
|
2411 |
|
2412 |
var form_html = jQuery( "."+comment_media_wrapper+widget_id );
|
@@ -2523,7 +2531,7 @@ function renderUploadercomment_media( widget_id, parent_id_type ) {
|
|
2523 |
|
2524 |
// Show/create text box to edit media title
|
2525 |
if ( jQuery( rtm_file_title_input ).length === 0 ) {
|
2526 |
-
jQuery( rtm_file_label ).parent( '.plupload_file_name' ).prepend( '<div id="' + rtm_file_title_wrapper_id + '" class="rtm-upload-edit-title-wrapper"><label>' + rtmedia_edit_media_info_upload.title + '</label><input type="text" class="rtm-upload-edit-title" id="' + rtm_file_title_id + '" value="' + file.title + '" style="width: 75%;" /></div><div id="' + rtm_file_desc_wrapper_id + '" class="rtm-upload-edit-desc-wrapper"><label>' + rtmedia_edit_media_info_upload.description + '</label><textarea class="rtm-upload-edit-desc" id="' + rtm_file_desc_id + '"></textarea></div><span id="' + rtm_file_save_id + '" title="Save Change" class="
|
2527 |
} else {
|
2528 |
jQuery( rtm_file_title_wrapper ).show();
|
2529 |
jQuery( rtm_file_desc_wrapper ).show();
|
684 |
|
685 |
// Show/create text box to edit media title
|
686 |
if ( jQuery( rtm_file_title_input ).length === 0 ) {
|
687 |
+
jQuery( rtm_file_label ).parent( '.plupload_file_name' ).prepend( '<div id="' + rtm_file_title_wrapper_id + '" class="rtm-upload-edit-title-wrapper"><label>' + rtmedia_edit_media_info_upload.title + '</label><input type="text" class="rtm-upload-edit-title" id="' + rtm_file_title_id + '" value="' + file.title + '" style="width: 75%;" /></div><div id="' + rtm_file_desc_wrapper_id + '" class="rtm-upload-edit-desc-wrapper"><label>' + rtmedia_edit_media_info_upload.description + '</label><textarea class="rtm-upload-edit-desc" id="' + rtm_file_desc_id + '"></textarea></div><span id="' + rtm_file_save_id + '" title="Save Change" class="dashicons dashicons-yes"></span>' );
|
688 |
} else {
|
689 |
jQuery( rtm_file_title_wrapper ).show();
|
690 |
jQuery( rtm_file_desc_wrapper ).show();
|
879 |
activity_id = rtnObj.activity_id;
|
880 |
if ( rtnObj.permalink != '' ) {
|
881 |
$( "#" + file.id + " .plupload_file_name" ).html( "<a href='" + rtnObj.permalink + "' target='_blank' title='" + rtnObj.permalink + "'>" + file.title.substring( 0, 40 ).replace( /(<([^>]+)>)/ig, "" ) + "</a>" );
|
882 |
+
$( "#" + file.id + " .plupload_media_edit" ).html( "<a href='" + rtnObj.permalink + "edit' target='_blank'><span title='" + rtmedia_edit_media + "'><i class='dashicons dashicons-edit'></i> " + rtmedia_edit + "</span></a>" );
|
883 |
$( "#" + file.id + " .plupload_delete" ).html( "<span id='" + rtnObj.media_id + "' class='rtmedia-delete-uploaded-media dashicons dashicons-dismiss' title='" + rtmedia_delete + "'></span>" );
|
884 |
}
|
885 |
|
1227 |
|
1228 |
// Show/create text box to edit media title
|
1229 |
if ( jQuery( rtm_file_title_input ).length === 0 ) {
|
1230 |
+
jQuery( rtm_file_label ).parent( '.plupload_file_name' ).prepend( '<div id="' + rtm_file_title_wrapper_id + '" class="rtm-upload-edit-title-wrapper"><label>' + rtmedia_edit_media_info_upload.title + '</label><input type="text" class="rtm-upload-edit-title" id="' + rtm_file_title_id + '" value="' + file.title + '" style="width: 75%;" /></div><div id="' + rtm_file_desc_wrapper_id + '" class="rtm-upload-edit-desc-wrapper"><label>' + rtmedia_edit_media_info_upload.description + '</label><textarea class="rtm-upload-edit-desc" id="' + rtm_file_desc_id + '"></textarea></div><span id="' + rtm_file_save_id + '" title="Save Change" class="dashicons dashicons-yes"></span>' );
|
1231 |
} else {
|
1232 |
jQuery( rtm_file_title_wrapper ).show();
|
1233 |
jQuery( rtm_file_desc_wrapper ).show();
|
1292 |
* if user want media and activity_text both require
|
1293 |
* By: Yahil
|
1294 |
*/
|
1295 |
+
if ( '' === jQuery( '#whats-new' ).val().trim() ) {
|
1296 |
+
if ( rtmedia_activity_text_with_attachment == 'disable' ) {
|
1297 |
+
if ( 0 === jQuery( '#rtmedia_upload_terms_conditions' ).length ) {
|
1298 |
+
$( '#whats-new' ).css( 'color', 'transparent' );
|
1299 |
+
$( '#whats-new' ).val( ' ' );
|
1300 |
+
}
|
1301 |
} else {
|
1302 |
jQuery('#whats-new-form').prepend('<div id="message" class="error bp-ajax-message" style="display: block;"><p> ' + rtmedia_empty_activity_msg + ' </p></div>')
|
1303 |
jQuery( '#whats-new' ).removeAttr( 'disabled' );
|
1394 |
}
|
1395 |
} );
|
1396 |
|
1397 |
+
var object = '';
|
1398 |
+
var item_id = 0;
|
1399 |
+
|
1400 |
+
if ( jQuery( '#whats-new-post-in' ).length ) {
|
1401 |
+
item_id = jQuery( '#whats-new-post-in' ).val();
|
1402 |
+
} else if ( jQuery( '.groups-header' ).length ) {
|
1403 |
+
item_id = jQuery( '.groups-header' ).attr( 'data-bp-item-id' );
|
1404 |
+
}
|
1405 |
+
|
1406 |
if ( item_id > 0 ) {
|
1407 |
object = 'group';
|
1408 |
} else {
|
1693 |
|
1694 |
|
1695 |
$( this ).attr( 'disabled', 'disabled' );
|
1696 |
+
//If string has only then set value as empty.
|
1697 |
+
if ( '' === comment_content_el.val().replace(/\ /g, '' ) ) {
|
1698 |
+
comment_content_el.val( '' );
|
1699 |
+
}
|
1700 |
$.ajax( {
|
1701 |
url: comment_form_el.attr( 'action' ),
|
1702 |
type: 'post',
|
1789 |
}
|
1790 |
|
1791 |
$( '.rtmedia-like span' ).html( data.next );
|
1792 |
+
$( '.rtmedia-like' ).attr( 'title', data.next );
|
1793 |
$( '.rtmedia-like-counter-wrap' ).html( data.person_text );
|
1794 |
$( '.rtm-like-loading' ).remove();
|
1795 |
$( that ).removeAttr( 'disabled' );
|
1895 |
if ( error == '' ) {
|
1896 |
upload_progress = '<div class="plupload_file_progress ui-widget-header" style="width: 0%;">';
|
1897 |
upload_progress += '</div>';
|
1898 |
+
icon = '<span id="label_' + file.id + '" class="dashicons dashicons-edit" title="' + rtmedia_backbone_strings.rtm_edit_file_name + '"></span>';
|
1899 |
} else if ( error.code == -600 ) {
|
1900 |
err_msg = ( uploader != '' ) ? rtmedia_max_file_msg + uploader.settings.max_file_size : window.file_size_info;
|
1901 |
title = 'title=\'' + err_msg + '\'';
|
1902 |
+
icon = '<i class="dashicons dashicons-info" ' + title + '></i>';
|
1903 |
} else if ( error.code == -601 ) {
|
1904 |
err_msg = error.message + '. ' + window.file_extn_info;
|
1905 |
title = 'title=\'' + err_msg + '\'';
|
1906 |
+
icon = '<i class="dashicons dashicons-info" ' + title + '></i>';
|
1907 |
}
|
1908 |
|
1909 |
var rtmedia_plupload_file = '<li class="plupload_file ui-state-default plupload_queue_li" id="' + file.id + '" ' + title + '>';
|
2414 |
jQuery( input_file_el ).click();
|
2415 |
file_dialog_open = false;
|
2416 |
}
|
2417 |
+
$(this).blur();
|
2418 |
} );
|
2419 |
|
2420 |
var form_html = jQuery( "."+comment_media_wrapper+widget_id );
|
2531 |
|
2532 |
// Show/create text box to edit media title
|
2533 |
if ( jQuery( rtm_file_title_input ).length === 0 ) {
|
2534 |
+
jQuery( rtm_file_label ).parent( '.plupload_file_name' ).prepend( '<div id="' + rtm_file_title_wrapper_id + '" class="rtm-upload-edit-title-wrapper"><label>' + rtmedia_edit_media_info_upload.title + '</label><input type="text" class="rtm-upload-edit-title" id="' + rtm_file_title_id + '" value="' + file.title + '" style="width: 75%;" /></div><div id="' + rtm_file_desc_wrapper_id + '" class="rtm-upload-edit-desc-wrapper"><label>' + rtmedia_edit_media_info_upload.description + '</label><textarea class="rtm-upload-edit-desc" id="' + rtm_file_desc_id + '"></textarea></div><span id="' + rtm_file_save_id + '" title="Save Change" class="dashicons dashicons-yes"></span>' );
|
2535 |
} else {
|
2536 |
jQuery( rtm_file_title_wrapper ).show();
|
2537 |
jQuery( rtm_file_desc_wrapper ).show();
|
app/assets/js/rtMedia.js
CHANGED
@@ -11,6 +11,10 @@ function apply_rtMagnificPopup( selector ) {
|
|
11 |
}
|
12 |
if ( typeof( rtmedia_lightbox_enabled ) != 'undefined' && rtmedia_lightbox_enabled == '1' ) { // If lightbox is enabled.
|
13 |
|
|
|
|
|
|
|
|
|
14 |
if ( $( '.activity-item .rtmedia-activity-container .rtmedia-list-item > a' ).siblings( 'p' ).children( 'a' ).length > 0 ) {
|
15 |
$( '.activity-item .rtmedia-activity-container .rtmedia-list-item > a' ).siblings( 'p' ).children( 'a' ).addClass( 'no-popup' );
|
16 |
}
|
@@ -52,6 +56,13 @@ function apply_rtMagnificPopup( selector ) {
|
|
52 |
if ( ( li.is( ':nth-last-child(2)' ) || li.is( ':last-child' ) ) && li.find( 'a' ).hasClass('rtmedia-list-item-a') ) { // If its last second media
|
53 |
var last_li = li.next();
|
54 |
if ( jQuery( '#rtMedia-galary-next' ).css( 'display' ) == 'block' ) { // If more medias are available
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
jQuery( '#rtMedia-galary-next' ).click(); // Load more
|
56 |
}
|
57 |
}
|
@@ -143,6 +154,21 @@ function apply_rtMagnificPopup( selector ) {
|
|
143 |
},
|
144 |
close: function( e ) {
|
145 |
//Console.log(e);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
146 |
rtmedia_single_page_popup_close();
|
147 |
},
|
148 |
BeforeChange: function( e ) {
|
@@ -1270,10 +1296,31 @@ function rtm_upload_terms_activity() {
|
|
1270 |
rtp_display_terms_warning( selector, rtmedia_upload_terms_check_terms_message );
|
1271 |
}
|
1272 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1273 |
}
|
1274 |
}
|
1275 |
|
1276 |
jQuery( document ).ready( function () {
|
1277 |
// Call function when document loaded.
|
1278 |
rtm_upload_terms_activity();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1279 |
});
|
|
11 |
}
|
12 |
if ( typeof( rtmedia_lightbox_enabled ) != 'undefined' && rtmedia_lightbox_enabled == '1' ) { // If lightbox is enabled.
|
13 |
|
14 |
+
var old_gallery_media;
|
15 |
+
var current_page;
|
16 |
+
var more_media_loaded = false;
|
17 |
+
|
18 |
if ( $( '.activity-item .rtmedia-activity-container .rtmedia-list-item > a' ).siblings( 'p' ).children( 'a' ).length > 0 ) {
|
19 |
$( '.activity-item .rtmedia-activity-container .rtmedia-list-item > a' ).siblings( 'p' ).children( 'a' ).addClass( 'no-popup' );
|
20 |
}
|
56 |
if ( ( li.is( ':nth-last-child(2)' ) || li.is( ':last-child' ) ) && li.find( 'a' ).hasClass('rtmedia-list-item-a') ) { // If its last second media
|
57 |
var last_li = li.next();
|
58 |
if ( jQuery( '#rtMedia-galary-next' ).css( 'display' ) == 'block' ) { // If more medias are available
|
59 |
+
|
60 |
+
if ( ! more_media_loaded ) {
|
61 |
+
old_gallery_media = mfp.ev.children();
|
62 |
+
more_media_loaded = true;
|
63 |
+
current_page = nextpage;
|
64 |
+
}
|
65 |
+
|
66 |
jQuery( '#rtMedia-galary-next' ).click(); // Load more
|
67 |
}
|
68 |
}
|
154 |
},
|
155 |
close: function( e ) {
|
156 |
//Console.log(e);
|
157 |
+
|
158 |
+
//If more media is loaded in lighbox then remove them set nextpage to default one.
|
159 |
+
if ( more_media_loaded ) {
|
160 |
+
|
161 |
+
mfp.ev.empty();
|
162 |
+
mfp.ev.append( old_gallery_media );
|
163 |
+
|
164 |
+
nextpage = current_page;
|
165 |
+
more_media_loaded = false;
|
166 |
+
|
167 |
+
if ( nextpage > 1 ) {
|
168 |
+
jQuery( '#rtMedia-galary-next' ).show();
|
169 |
+
}
|
170 |
+
}
|
171 |
+
|
172 |
rtmedia_single_page_popup_close();
|
173 |
},
|
174 |
BeforeChange: function( e ) {
|
1296 |
rtp_display_terms_warning( selector, rtmedia_upload_terms_check_terms_message );
|
1297 |
}
|
1298 |
});
|
1299 |
+
|
1300 |
+
var bp_legacy_form = jQuery( '#whats-new-form' );
|
1301 |
+
|
1302 |
+
// Re-enable hidden inputs disabled in the activity post form.
|
1303 |
+
if ( bp_legacy_form.length > 0 ) {
|
1304 |
+
// Add upload terms element selector to work when direct upload is enabled.
|
1305 |
+
jQuery( '#whats-new-form, #rtmedia_upload_terms_conditions' ).on( 'click', function ( event ) {
|
1306 |
+
var hidden_fields = bp_legacy_form.find( 'input:hidden' );
|
1307 |
+
hidden_fields.each( function() {
|
1308 |
+
jQuery(this).prop( 'disabled', false );
|
1309 |
+
} );
|
1310 |
+
} );
|
1311 |
+
}
|
1312 |
}
|
1313 |
}
|
1314 |
|
1315 |
jQuery( document ).ready( function () {
|
1316 |
// Call function when document loaded.
|
1317 |
rtm_upload_terms_activity();
|
1318 |
+
|
1319 |
+
// Avoid Lightbox conflict due to class has-sidebar in theme 2017 v2.1.
|
1320 |
+
if( jQuery( 'body' ).hasClass( 'has-sidebar' ) && 0 === jQuery( '#secondary' ).length ) {
|
1321 |
+
if ( jQuery( '.rtmedia-single-container' ).length || jQuery( '.rtmedia-container' ).length ) {
|
1322 |
+
jQuery( 'body' ).removeClass( 'has-sidebar' );
|
1323 |
+
}
|
1324 |
+
}
|
1325 |
});
|
1326 |
+
|
app/assets/js/rtmedia.min.js
CHANGED
@@ -3,5 +3,5 @@
|
|
3 |
* @package rtMedia
|
4 |
*/
|
5 |
|
6 |
-
function apply_rtMagnificPopup(a){jQuery("document").ready(function(b){var c="";c="undefined"==typeof rtmedia_load_more?"Loading media":rtmedia_load_more,"undefined"!=typeof rtmedia_lightbox_enabled&&"1"==rtmedia_lightbox_enabled&&(b(".activity-item .rtmedia-activity-container .rtmedia-list-item > a").siblings("p").children("a").length>0&&b(".activity-item .rtmedia-activity-container .rtmedia-list-item > a").siblings("p").children("a").addClass("no-popup"),rtMagnificPopup=jQuery(a).magnificPopup({delegate:"a:not(.no-popup, .mejs-time-slider, .mejs-volume-slider, .mejs-horizontal-volume-slider)",type:"ajax",fixedContentPos:!0,fixedBgPos:!0,tLoading:c+" #%curr%...",mainClass:"mfp-img-mobile",preload:[1,3],closeOnBgClick:!0,gallery:{enabled:!0,navigateByImgClick:!0,arrowMarkup:"",preload:[0,1]},image:{tError:'<a href="%url%">The image #%curr%</a> could not be loaded.',titleSrc:function(a){return a.el.attr("title")+"<small>by Marsel Van Oosten</small>"}},callbacks:{ajaxContentAdded:function(){a=jQuery.magnificPopup.instance,1===jQuery(a.items).size()&&jQuery(".mfp-arrow").remove();var a=jQuery.magnificPopup.instance,c=a.currItem.el,d=c.parent();if(d.is("li")||(d=d.parent()),(d.is(":nth-last-child(2)")||d.is(":last-child"))&&d.find("a").hasClass("rtmedia-list-item-a")){d.next();"block"==jQuery("#rtMedia-galary-next").css("display")&&jQuery("#rtMedia-galary-next").click()}var e=a.items.length;if(a.index==e-1&&!d.is(":last-child"))return void c.click();var f={};"undefined"!=typeof _wpmejsSettings&&(f.pluginPath=_wpmejsSettings.pluginPath);var g=jQuery(".rtmedia-container .rtmedia-single-meta").height(),h=!1;void 0!==a&&void 0!==a.probablyMobile&&1==a.probablyMobile&&(h=!0),b(".mfp-content .rtmedia-single-media .wp-audio-shortcode,.mfp-content .rtmedia-single-media .wp-video-shortcode,.mfp-content .rtmedia-single-media .bp_media_content video").attr("autoplay",!0),h&&b(".mfp-content .rtmedia-single-media .wp-video-shortcode,.mfp-content .rtmedia-single-media .bp_media_content video").attr("muted",!1),b(".mfp-content .rtmedia-single-media .wp-audio-shortcode,.mfp-content .rtmedia-single-media .wp-video-shortcode,.mfp-content .rtmedia-single-media .bp_media_content video").mediaelementplayer({classPrefix:"mejs-",defaultVideoWidth:480,hideVolumeOnTouchDevices:!1,features:["playpause","progress","current","volume","fullscreen"],defaultVideoHeight:270,alwaysShowControls:h,enableAutosize:!0,clickToPlayPause:!0,videoHeight:-1,success:function(a,c){a.addEventListener("loadeddata",function(c){var d=b(a).height(),e=b(window).height(),f=jQuery("div.rtm-ltb-action-container").height(),f=f+50,h=g-f;d>e&&jQuery(".rtmedia-container #rtmedia-single-media-container .mejs-container").attr("style","height:"+h+"px !important; transition:0.2s")},!1),h&&b(a).hasClass("wp-video-shortcode")?jQuery("body").on("touchstart",".mejs-overlay-button",function(b){a.paused?a.play():a.pause()}):a.pause()}}),b(".mfp-content .mejs-audio .mejs-controls").css("position","relative"),rtMediaHook.call("rtmedia_js_popup_after_content_added",[]),"undefined"!=typeof bp&&void 0!==bp.mentions&&void 0!==bp.mentions.users&&(b("#atwho-container #atwho-ground-comment_content").remove(),b("#comment_content").bp_mentions(bp.mentions.users)),rtmedia_reset_video_and_audio_for_popup(),apply_rtMagnificPopup(".rtmedia-list-media.rtm-gallery-list, .rtmedia-activity-container ul.rtmedia-list, #bp-media-list,.bp-media-sc-list, li.media.album_updated ul,ul.bp-media-list-media, li.activity-item div.activity-content div.activity-inner div.bp_media_content, .rtm-bbp-container, ul.rtm-comment-container")},open:function(){var a=jQuery(".mfp-bg"),b=jQuery(".mfp-wrap");a.height(a.height()+b.height())},close:function(a){rtmedia_single_page_popup_close()},BeforeChange:function(a){}}})),jQuery(document).ajaxComplete(function(){jQuery("[id^=imgedit-leaving]").filter(function(){var a=jQuery(this).text();jQuery(this).text(a.replace("OK","Save"))})})})}function rtmedia_init_action_dropdown(a){var b,c;jQuery(a+" .click-nav > span,"+a+" .click-nav > div").toggleClass("no-js js"),jQuery(a+" .click-nav .js ul").hide(),jQuery(a+" .click-nav .clicker").click(function(a){b=jQuery("#rtm-media-options .click-nav .clicker").next("ul"),c=jQuery(this).next("ul"),jQuery.each(b,function(a,b){jQuery(b).html()!=c.html()&&jQuery(b).hide()}),jQuery(c).toggle(),a.stopPropagation()})}function bp_media_create_element(a){return!1}function rtmedia_version_compare(a,b){if(typeof a+typeof b!="stringstring")return!1;for(var c=a.split("."),d=b.split("."),e=0,f=Math.max(c.length,d.length);e<f;e++){if(c[e]&&!d[e]&&parseInt(c[e])>0||parseInt(c[e])>parseInt(d[e]))return!0;if(d[e]&&!c[e]&&parseInt(d[e])>0||parseInt(c[e])<parseInt(d[e]))return!1}return!0}function rtm_is_element_exist(a){return jQuery(a).length>0}function rtm_masonry_reload(a){setTimeout(function(){a.masonry("reload")},250)}function rtm_search_media_text_validation(){""===jQuery("#media_search_input").val()?jQuery("#media_search").css("cursor","not-allowed"):jQuery("#media_search").css("cursor","pointer")}function rtmediaGetParameterByName(a){a=a.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]");var b=new RegExp("[\\?&]"+a+"=([^&#]*)"),c=b.exec(location.search);return null==c?"":decodeURIComponent(c[1].replace(/\+/g," "))}function rtmedia_single_media_alert_message(a,b,c){var d="rtmedia-success";"warning"==b&&(d="rtmedia-warning");var e=!1;jQuery(".rtmedia-message-container").each(function(a,b){return b=jQuery(b),c&&b.hasClass("rtmedia-empty-comment-error-class")?(b.remove(),e=!0,!1):void 0!==c||b.hasClass("rtmedia-empty-comment-error-class")?void 0:(b.remove(),e=!0,!1)});var f=jQuery("<div>",{title:"Click to dismiss",class:"rtmedia-message-container"+(c?" rtmedia-empty-comment-error-class":""),style:"margin:1em 0;"}),g=jQuery("<span>",{class:d});g.html(a),g.appendTo(f);var h;c?(h=jQuery("#rt_media_comment_form"),jQuery("#comment_content").focus()):void 0===c&&(h=jQuery(".rtmedia-single-media .rtmedia-media"),h.css("opacity","0.2")),h.after(f),e&&(g.css({border:"2px solid #884646"}),setTimeout(function(){g.css({border:"none"})},500)),setTimeout(function(){f.remove(),void 0===c&&h.css("opacity","1")},3e3),f.click(function(){f.remove(),void 0===c&&h.css("opacity","1")})}function rtmedia_gallery_action_alert_message(a,b){var c="rtmedia-success";"warning"==b&&(c="rtmedia-warning");jQuery("body").append('<div class="rtmedia-gallery-alert-container"> </div>'),jQuery(".rtmedia-gallery-alert-container").append("<div class='rtmedia-gallery-message-box'><span class='"+c+"'>"+a+" </span></div>"),setTimeout(function(){jQuery(".rtmedia-gallery-alert-container").remove()},3e3),jQuery(".rtmedia-gallery-message-box").click(function(){jQuery(".rtmedia-gallery-alert-container").remove()})}function rtmedia_activity_masonry(){jQuery("#activity-stream .rtmedia-activity-container .rtmedia-list").masonry({itemSelector:".rtmedia-list-item",gutter:7});var a=0,b=setInterval(function(){a+=1,5===a&&clearInterval(b),jQuery.each(jQuery(".rtmedia-activity-container .rtmedia-list.masonry .rtmedia-item-title"),function(a,b){jQuery(b).width(jQuery(b).siblings(".rtmedia-item-thumbnail").children("img").width())}),rtm_masonry_reload(jQuery("#activity-stream .rtmedia-activity-container .rtmedia-list"))},1e3)}function get_parameter(a,b){if(!a)return!1;b||(b=window.location.href);var a=a.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]"),c=a+"=([^&#]*)",d=new RegExp(c),e=d.exec(b);return null!==e&&e[1]}function rtm_upload_terms_activity(){jQuery("#rtmedia_upload_terms_conditions").length>0&&jQuery("#bp-nouveau-activity-form").on("click","#aw-whats-new-submit",function(a){var b=jQuery("#whats-new-form"),c=b.find("#rtmedia_upload_terms_conditions");if(0!==c.length&&!1===c.prop("checked")&&0===b.find("#message").length){a.preventDefault();var d=b.find(".rtmedia-upload-terms");rtp_display_terms_warning(d,rtmedia_upload_terms_check_terms_message)}})}!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):window.jQuery||window.Zepto)}(function(a){var b,c,d,e,f,g,h=function(){},i=!!window.jQuery,j=a(window),k=function(a,c){b.ev.on("mfp"+a+".mfp",c)},l=function(b,c,d,e){var f=document.createElement("div");return f.className="mfp-"+b,d&&(f.innerHTML=d),e?c&&c.appendChild(f):(f=a(f),c&&f.appendTo(c)),f},m=function(c,d){b.ev.triggerHandler("mfp"+c,d),b.st.callbacks&&(c=c.charAt(0).toLowerCase()+c.slice(1),b.st.callbacks[c]&&b.st.callbacks[c].apply(b,a.isArray(d)?d:[d]))},n=function(c){return c===g&&b.currTemplate.closeBtn||(b.currTemplate.closeBtn=a(b.st.closeMarkup.replace("%title%",b.st.tClose)),g=c),b.currTemplate.closeBtn},o=function(){a.magnificPopup.instance||(b=new h,b.init(),a.magnificPopup.instance=b)},p=function(){var a=document.createElement("p").style,b=["ms","O","Moz","Webkit"];if(void 0!==a.transition)return!0;for(;b.length;)if(b.pop()+"Transition"in a)return!0;return!1};h.prototype={constructor:h,init:function(){var c=navigator.appVersion;b.isIE7=-1!==c.indexOf("MSIE 7."),b.isIE8=-1!==c.indexOf("MSIE 8."),b.isLowIE=b.isIE7||b.isIE8,b.isAndroid=/android/gi.test(c),b.isIOS=/iphone|ipad|ipod/gi.test(c),b.supportsTransition=p(),b.probablyMobile=b.isAndroid||b.isIOS||/(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent),d=a(document),b.popupsCache={}},open:function(c){var e;if(!1===c.isObj){b.items=c.items.toArray(),b.index=0;var g,h=c.items;for(e=0;e<h.length;e++)if(g=h[e],g.parsed&&(g=g.el[0]),g===c.el[0]){b.index=e;break}}else b.items=a.isArray(c.items)?c.items:[c.items],b.index=c.index||0;if(b.isOpen)return void b.updateItemHTML();b.types=[],f="",c.mainEl&&c.mainEl.length?b.ev=c.mainEl.eq(0):b.ev=d,c.key?(b.popupsCache[c.key]||(b.popupsCache[c.key]={}),b.currTemplate=b.popupsCache[c.key]):b.currTemplate={},b.st=a.extend(!0,{},a.magnificPopup.defaults,c),b.fixedContentPos="auto"===b.st.fixedContentPos?!b.probablyMobile:b.st.fixedContentPos,b.st.modal&&(b.st.closeOnContentClick=!1,b.st.closeOnBgClick=!1,b.st.showCloseBtn=!1,b.st.enableEscapeKey=!1),b.bgOverlay||(b.bgOverlay=l("bg").on("click.mfp",function(){b.close()}),b.wrap=l("wrap").attr("tabindex",-1).on("click.mfp",function(a){b._checkIfClose(a.target)&&b.close()}),b.container=l("container",b.wrap)),b.contentContainer=l("content"),b.st.preloader&&(b.preloader=l("preloader",b.container,b.st.tLoading));var i=a.magnificPopup.modules;for(e=0;e<i.length;e++){var o=i[e];o=o.charAt(0).toUpperCase()+o.slice(1),b["init"+o].call(b)}m("BeforeOpen"),b.st.showCloseBtn&&(b.st.closeBtnInside?(k("MarkupParse",function(a,b,c,d){c.close_replaceWith=n(d.type)}),f+=" mfp-close-btn-in"):b.wrap.append(n())),b.st.alignTop&&(f+=" mfp-align-top"),b.fixedContentPos?b.wrap.css({overflow:b.st.overflowY,overflowX:"hidden",overflowY:b.st.overflowY}):b.wrap.css({top:j.scrollTop(),position:"absolute"}),(!1===b.st.fixedBgPos||"auto"===b.st.fixedBgPos&&!b.fixedContentPos)&&b.bgOverlay.css({height:d.height(),position:"absolute"}),b.st.enableEscapeKey&&d.on("keyup.mfp",function(a){27===a.keyCode&&b.close()}),j.on("resize.mfp",function(){b.updateSize()}),b.st.closeOnContentClick||(f+=" mfp-auto-cursor"),f&&b.wrap.addClass(f);var p=b.wH=j.height(),q={};if(b.fixedContentPos&&b._hasScrollBar(p)){var r=b._getScrollbarSize();r&&(q.marginRight=r)}b.fixedContentPos&&(b.isIE7?a("body, html").css("overflow","hidden"):q.overflow="hidden");var s=b.st.mainClass;return b.isIE7&&(s+=" mfp-ie7"),s&&b._addClassToMFP(s),b.updateItemHTML(),m("BuildControls"),a("html").css(q),b.bgOverlay.add(b.wrap).prependTo(b.st.prependTo||a(document.body)),b._lastFocusedEl=document.activeElement,setTimeout(function(){b.content?(b._addClassToMFP("mfp-ready"),b._setFocus()):b.bgOverlay.addClass("mfp-ready"),d.on("focusin.mfp",b._onFocusIn)},16),b.isOpen=!0,b.updateSize(p),m("Open"),c},close:function(){b.isOpen&&(m("BeforeClose"),b.isOpen=!1,b.st.removalDelay&&!b.isLowIE&&b.supportsTransition?(b._addClassToMFP("mfp-removing"),setTimeout(function(){b._close()},b.st.removalDelay)):b._close())},_close:function(){m("Close");var c="mfp-removing mfp-ready ";if(b.bgOverlay.detach(),b.wrap.detach(),b.container.empty(),b.st.mainClass&&(c+=b.st.mainClass+" "),b._removeClassFromMFP(c),b.fixedContentPos){var e={marginRight:""};b.isIE7?a("body, html").css("overflow",""):e.overflow="",a("html").css(e)}d.off("keyup.mfp focusin.mfp"),b.ev.off(".mfp"),b.wrap.attr("class","mfp-wrap").removeAttr("style"),b.bgOverlay.attr("class","mfp-bg"),b.container.attr("class","mfp-container"),!b.st.showCloseBtn||b.st.closeBtnInside&&!0!==b.currTemplate[b.currItem.type]||b.currTemplate.closeBtn&&b.currTemplate.closeBtn.detach(),b._lastFocusedEl&&a(b._lastFocusedEl).focus(),b.currItem=null,b.content=null,b.currTemplate=null,b.prevHeight=0,m("AfterClose")},updateSize:function(a){if(b.isIOS){var c=document.documentElement.clientWidth/window.innerWidth,d=window.innerHeight*c;b.wrap.css("height",d),b.wH=d}else b.wH=a||j.height();b.fixedContentPos||b.wrap.css("height",b.wH),m("Resize")},updateItemHTML:function(){var c=b.items[b.index];b.contentContainer.detach(),b.content&&b.content.detach(),c.parsed||(c=b.parseEl(b.index));var d=c.type;if(m("BeforeChange",[b.currItem?b.currItem.type:"",d]),b.currItem=c,!b.currTemplate[d]){var f=!!b.st[d]&&b.st[d].markup;m("FirstMarkupParse",f),b.currTemplate[d]=!f||a(f)}e&&e!==c.type&&b.container.removeClass("mfp-"+e+"-holder");var g=b["get"+d.charAt(0).toUpperCase()+d.slice(1)](c,b.currTemplate[d]);b.appendContent(g,d),c.preloaded=!0,m("Change",c),e=c.type,b.container.prepend(b.contentContainer),m("AfterChange")},appendContent:function(a,c){b.content=a,a?b.st.showCloseBtn&&b.st.closeBtnInside&&!0===b.currTemplate[c]?b.content.find(".mfp-close").length||b.content.append(n()):b.content=a:b.content="",m("BeforeAppend"),b.container.addClass("mfp-"+c+"-holder"),b.contentContainer.append(b.content)},parseEl:function(c){var d,e=b.items[c];if(e.tagName?e={el:a(e)}:(d=e.type,e={data:e,src:e.src}),e.el){for(var f=b.types,g=0;g<f.length;g++)if(e.el.hasClass("mfp-"+f[g])){d=f[g];break}e.src=e.el.attr("data-mfp-src"),e.src||(e.src=e.el.attr("href"))}return e.type=d||b.st.type||"inline",e.index=c,e.parsed=!0,b.items[c]=e,m("ElementParse",e),b.items[c]},addGroup:function(a,c){var d=function(d){d.mfpEl=this,b._openClick(d,a,c)};c||(c={});var e="click.magnificPopup";c.mainEl=a,c.items?(c.isObj=!0,a.off(e).on(e,d)):(c.isObj=!1,c.delegate?a.off(e).on(e,c.delegate,d):(c.items=a,a.off(e).on(e,d)))},_openClick:function(c,d,e){if((void 0!==e.midClick?e.midClick:a.magnificPopup.defaults.midClick)||2!==c.which&&!c.ctrlKey&&!c.metaKey){var f=void 0!==e.disableOn?e.disableOn:a.magnificPopup.defaults.disableOn;if(f)if(a.isFunction(f)){if(!f.call(b))return!0}else if(j.width()<f)return!0;c.type&&(c.preventDefault(),b.isOpen&&c.stopPropagation()),e.el=a(c.mfpEl),e.delegate&&(e.items=d.find(e.delegate)),b.open(e)}},updateStatus:function(a,d){if(b.preloader){c!==a&&b.container.removeClass("mfp-s-"+c),d||"loading"!==a||(d=b.st.tLoading);var e={status:a,text:d};m("UpdateStatus",e),a=e.status,d=e.text,b.preloader.html(d),b.preloader.find("a").on("click",function(a){a.stopImmediatePropagation()}),b.container.addClass("mfp-s-"+a),c=a}},_checkIfClose:function(c){if(!a(c).hasClass("mfp-prevent-close")){var d=b.st.closeOnContentClick,e=b.st.closeOnBgClick;if(d&&e)return!0;if(!b.content||a(c).hasClass("mfp-close")||b.preloader&&c===b.preloader[0])return!0;if(c===b.content[0]||a.contains(b.content[0],c)){if(d)return!0}else if(e&&a.contains(document,c))return!0;return!1}},_addClassToMFP:function(a){b.bgOverlay.addClass(a),b.wrap.addClass(a)},_removeClassFromMFP:function(a){this.bgOverlay.removeClass(a),b.wrap.removeClass(a)},_hasScrollBar:function(a){return(b.isIE7?d.height():document.body.scrollHeight)>(a||j.height())},_setFocus:function(){(b.st.focus?b.content.find(b.st.focus).eq(0):b.wrap).focus()},_onFocusIn:function(c){if(c.target!==b.wrap[0]&&!a.contains(b.wrap[0],c.target))return b._setFocus(),!1},_parseMarkup:function(b,c,d){var e;d.data&&(c=a.extend(d.data,c)),m("MarkupParse",[b,c,d]),a.each(c,function(a,c){if(void 0===c||!1===c)return!0;if(e=a.split("_"),e.length>1){var d=b.find(".mfp-"+e[0]);if(d.length>0){var f=e[1];"replaceWith"===f?d[0]!==c[0]&&d.replaceWith(c):"img"===f?d.is("img")?d.attr("src",c):d.replaceWith('<img src="'+c+'" class="'+d.attr("class")+'" />'):d.attr(e[1],c)}}else b.find(".mfp-"+a).html(c)})},_getScrollbarSize:function(){if(void 0===b.scrollbarSize){var a=document.createElement("div");a.style.cssText="width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;",document.body.appendChild(a),b.scrollbarSize=a.offsetWidth-a.clientWidth,document.body.removeChild(a)}return b.scrollbarSize}},a.magnificPopup={instance:null,proto:h.prototype,modules:[],open:function(b,c){return o(),b=b?a.extend(!0,{},b):{},b.isObj=!0,b.index=c||0,this.instance.open(b)},close:function(){return a.magnificPopup.instance&&a.magnificPopup.instance.close()},registerModule:function(b,c){c.options&&(a.magnificPopup.defaults[b]=c.options),a.extend(this.proto,c.proto),this.modules.push(b)},defaults:{disableOn:0,key:null,midClick:!1,mainClass:"",preloader:!0,focus:"",closeOnContentClick:!1,closeOnBgClick:!0,closeBtnInside:!0,showCloseBtn:!0,enableEscapeKey:!0,modal:!1,alignTop:!1,removalDelay:0,prependTo:null,fixedContentPos:"auto",fixedBgPos:"auto",overflowY:"auto",closeMarkup:'<button title="%title%" type="button" class="mfp-close">×</button>',tClose:"Close (Esc)",tLoading:"Loading..."}},a.fn.magnificPopup=function(c){o();var d=a(this);if("string"==typeof c)if("open"===c){var e,f=i?d.data("magnificPopup"):d[0].magnificPopup,g=parseInt(arguments[1],10)||0;f.items?e=f.items[g]:(e=d,f.delegate&&(e=e.find(f.delegate)),e=e.eq(g)),b._openClick({mfpEl:e},d,f)}else b.isOpen&&b[c].apply(b,Array.prototype.slice.call(arguments,1));else c=a.extend(!0,{},c),i?d.data("magnificPopup",c):d[0].magnificPopup=c,b.addGroup(d,c);return d};var q,r,s,t=function(){s&&(r.after(s.addClass(q)).detach(),s=null)};a.magnificPopup.registerModule("inline",{options:{hiddenClass:"hide",markup:"",tNotFound:"Content not found"},proto:{initInline:function(){b.types.push("inline"),k("Close.inline",function(){t()})},getInline:function(c,d){if(t(),c.src){var e=b.st.inline,f=a(c.src);if(f.length){var g=f[0].parentNode;g&&g.tagName&&(r||(q=e.hiddenClass,r=l(q),q="mfp-"+q),s=f.after(r).detach().removeClass(q)),b.updateStatus("ready")}else b.updateStatus("error",e.tNotFound),f=a("<div>");return c.inlineElement=f,f}return b.updateStatus("ready"),b._parseMarkup(d,{},c),d}}});var u,v=function(){u&&a(document.body).removeClass(u)},w=function(){v(),b.req&&b.req.abort()};a.magnificPopup.registerModule("ajax",{options:{settings:null,cursor:"mfp-ajax-cur",tError:'<a href="%url%">The content</a> could not be loaded.'},proto:{initAjax:function(){b.types.push("ajax"),u=b.st.ajax.cursor,k("Close.ajax",w),k("BeforeChange.ajax",w)},getAjax:function(c){u&&a(document.body).addClass(u),b.updateStatus("loading");var d=a.extend({url:c.src,success:function(d,e,f){var g={data:d,xhr:f};m("ParseAjax",g),b.appendContent(a(g.data),"ajax"),c.finished=!0,v(),b._setFocus(),setTimeout(function(){b.wrap.addClass("mfp-ready")},16),b.updateStatus("ready"),m("AjaxContentAdded")},error:function(){v(),c.finished=c.loadError=!0,b.updateStatus("error",b.st.ajax.tError.replace("%url%",c.src))}},b.st.ajax.settings);return b.req=a.ajax(d),""}}});var x,y=function(c){if(c.data&&void 0!==c.data.title)return c.data.title;var d=b.st.image.titleSrc;if(d){if(a.isFunction(d))return d.call(b,c);if(c.el)return c.el.attr(d)||""}return""};a.magnificPopup.registerModule("image",{options:{markup:'<div class="mfp-figure"><div class="mfp-close"></div><figure><div class="mfp-img"></div><figcaption><div class="mfp-bottom-bar"><div class="mfp-title"></div><div class="mfp-counter"></div></div></figcaption></figure></div>',cursor:"mfp-zoom-out-cur",titleSrc:"title",verticalFit:!0,tError:'<a href="%url%">The image</a> could not be loaded.'},proto:{initImage:function(){var c=b.st.image,d=".image";b.types.push("image"),k("Open"+d,function(){"image"===b.currItem.type&&c.cursor&&a(document.body).addClass(c.cursor)}),k("Close"+d,function(){c.cursor&&a(document.body).removeClass(c.cursor),j.off("resize.mfp")}),k("Resize"+d,b.resizeImage),b.isLowIE&&k("AfterChange",b.resizeImage)},resizeImage:function(){var a=b.currItem;if(a&&a.img&&b.st.image.verticalFit){var c=0;b.isLowIE&&(c=parseInt(a.img.css("padding-top"),10)+parseInt(a.img.css("padding-bottom"),10)),a.img.css("max-height",b.wH-c)}},_onImageHasSize:function(a){a.img&&(a.hasSize=!0,x&&clearInterval(x),a.isCheckingImgSize=!1,m("ImageHasSize",a),a.imgHidden&&(b.content&&b.content.removeClass("mfp-loading"),a.imgHidden=!1))},findImageSize:function(a){var c=0,d=a.img[0],e=function(f){x&&clearInterval(x),x=setInterval(function(){if(d.naturalWidth>0)return void b._onImageHasSize(a);c>200&&clearInterval(x),c++,3===c?e(10):40===c?e(50):100===c&&e(500)},f)};e(1)},getImage:function(c,d){var e=0,f=function(){c&&(c.img[0].complete?(c.img.off(".mfploader"),c===b.currItem&&(b._onImageHasSize(c),b.updateStatus("ready")),c.hasSize=!0,c.loaded=!0,m("ImageLoadComplete")):(e++,e<200?setTimeout(f,100):g()))},g=function(){c&&(c.img.off(".mfploader"),c===b.currItem&&(b._onImageHasSize(c),b.updateStatus("error",h.tError.replace("%url%",c.src))),c.hasSize=!0,c.loaded=!0,c.loadError=!0)},h=b.st.image,i=d.find(".mfp-img");if(i.length){var j=document.createElement("img");j.className="mfp-img",c.el&&c.el.find("img").length&&(j.alt=c.el.find("img").attr("alt")),c.img=a(j).on("load.mfploader",f).on("error.mfploader",g),j.src=c.src,i.is("img")&&(c.img=c.img.clone()),j=c.img[0],j.naturalWidth>0?c.hasSize=!0:j.width||(c.hasSize=!1)}return b._parseMarkup(d,{title:y(c),img_replaceWith:c.img},c),b.resizeImage(),c.hasSize?(x&&clearInterval(x),c.loadError?(d.addClass("mfp-loading"),b.updateStatus("error",h.tError.replace("%url%",c.src))):(d.removeClass("mfp-loading"),b.updateStatus("ready")),d):(b.updateStatus("loading"),c.loading=!0,c.hasSize||(c.imgHidden=!0,d.addClass("mfp-loading"),b.findImageSize(c)),d)}}});var z,A=function(){return void 0===z&&(z=void 0!==document.createElement("p").style.MozTransform),z};a.magnificPopup.registerModule("zoom",{options:{enabled:!1,easing:"ease-in-out",duration:300,opener:function(a){return a.is("img")?a:a.find("img")}},proto:{initZoom:function(){var a,c=b.st.zoom,d=".zoom";if(c.enabled&&b.supportsTransition){var e,f,g=c.duration,h=function(a){var b=a.clone().removeAttr("style").removeAttr("class").addClass("mfp-animated-image"),d="all "+c.duration/1e3+"s "+c.easing,e={position:"fixed",zIndex:9999,left:0,top:0,"-webkit-backface-visibility":"hidden"},f="transition";return e["-webkit-"+f]=e["-moz-"+f]=e["-o-"+f]=e[f]=d,b.css(e),b},i=function(){b.content.css("visibility","visible")};k("BuildControls"+d,function(){if(b._allowZoom()){if(clearTimeout(e),b.content.css("visibility","hidden"),!(a=b._getItemToZoom()))return void i();f=h(a),f.css(b._getOffset()),b.wrap.append(f),e=setTimeout(function(){f.css(b._getOffset(!0)),e=setTimeout(function(){i(),setTimeout(function(){f.remove(),a=f=null,m("ZoomAnimationEnded")},16)},g)},16)}}),k("BeforeClose"+d,function(){if(b._allowZoom()){if(clearTimeout(e),b.st.removalDelay=g,!a){if(!(a=b._getItemToZoom()))return;f=h(a)}f.css(b._getOffset(!0)),b.wrap.append(f),b.content.css("visibility","hidden"),setTimeout(function(){f.css(b._getOffset())},16)}}),k("Close"+d,function(){b._allowZoom()&&(i(),f&&f.remove(),a=null)})}},_allowZoom:function(){return"image"===b.currItem.type},_getItemToZoom:function(){return!!b.currItem.hasSize&&b.currItem.img},_getOffset:function(c){var d;d=c?b.currItem.img:b.st.zoom.opener(b.currItem.el||b.currItem);var e=d.offset(),f=parseInt(d.css("padding-top"),10),g=parseInt(d.css("padding-bottom"),10);e.top-=a(window).scrollTop()-f;var h={width:d.width(),height:(i?d.innerHeight():d[0].offsetHeight)-g-f};return A()?h["-moz-transform"]=h.transform="translate("+e.left+"px,"+e.top+"px)":(h.left=e.left,h.top=e.top),h}}});var B=function(a){if(b.currTemplate.iframe){var c=b.currTemplate.iframe.find("iframe");c.length&&(a||(c[0].src="//about:blank"),b.isIE8&&c.css("display",a?"block":"none"))}};a.magnificPopup.registerModule("iframe",{options:{markup:'<div class="mfp-iframe-scaler"><div class="mfp-close"></div><iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe></div>',srcAction:"iframe_src",patterns:{youtube:{index:"youtube.com",id:"v=",src:"//www.youtube.com/embed/%id%?autoplay=1"},vimeo:{index:"vimeo.com/",id:"/",src:"//player.vimeo.com/video/%id%?autoplay=1"},gmaps:{index:"//maps.google.",src:"%id%&output=embed"}}},proto:{initIframe:function(){b.types.push("iframe"),k("BeforeChange",function(a,b,c){b!==c&&("iframe"===b?B():"iframe"===c&&B(!0))}),k("Close.iframe",function(){B()})},getIframe:function(c,d){var e=c.src,f=b.st.iframe;a.each(f.patterns,function(){if(e.indexOf(this.index)>-1)return this.id&&(e="string"==typeof this.id?e.substr(e.lastIndexOf(this.id)+this.id.length,e.length):this.id.call(this,e)),e=this.src.replace("%id%",e),!1});var g={};return f.srcAction&&(g[f.srcAction]=e),b._parseMarkup(d,g,c),b.updateStatus("ready"),d}}});var C=function(a){var c=b.items.length;return a>c-1?a-c:a<0?c+a:a},D=function(a,b,c){return a.replace(/%curr%/gi,b+1).replace(/%total%/gi,c)};a.magnificPopup.registerModule("gallery",{options:{enabled:!1,arrowMarkup:'<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',preload:[0,2],navigateByImgClick:!0,arrows:!0,tPrev:"Previous (Left arrow key)",tNext:"Next (Right arrow key)",tCounter:"%curr% of %total%"},proto:{initGallery:function(){var c=b.st.gallery,e=".mfp-gallery",g=Boolean(a.fn.mfpFastClick);if(b.direction=!0,!c||!c.enabled)return!1;f+=" mfp-gallery",k("Open"+e,function(){c.navigateByImgClick&&b.wrap.on("click"+e,".mfp-img",function(){if(b.items.length>1)return b.next(),!1}),d.on("keydown"+e,function(a){37===a.keyCode?b.prev():39===a.keyCode&&b.next()})}),k("UpdateStatus"+e,function(a,c){c.text&&(c.text=D(c.text,b.currItem.index,b.items.length))}),k("MarkupParse"+e,function(a,d,e,f){var g=b.items.length;e.counter=g>1?D(c.tCounter,f.index,g):""}),k("BuildControls"+e,function(){if(b.items.length>1&&c.arrows&&!b.arrowLeft){var d=c.arrowMarkup,e=b.arrowLeft=a(d.replace(/%title%/gi,c.tPrev).replace(/%dir%/gi,"left")).addClass("mfp-prevent-close"),f=b.arrowRight=a(d.replace(/%title%/gi,c.tNext).replace(/%dir%/gi,"right")).addClass("mfp-prevent-close"),h=g?"mfpFastClick":"click";e[h](function(){b.prev()}),f[h](function(){b.next()}),b.isIE7&&(l("b",e[0],!1,!0),l("a",e[0],!1,!0),l("b",f[0],!1,!0),l("a",f[0],!1,!0)),b.container.append(e.add(f))}}),k("Change"+e,function(){b._preloadTimeout&&clearTimeout(b._preloadTimeout),b._preloadTimeout=setTimeout(function(){b.preloadNearbyImages(),b._preloadTimeout=null},16)}),k("Close"+e,function(){d.off(e),b.wrap.off("click"+e),b.arrowLeft&&g&&b.arrowLeft.add(b.arrowRight).destroyMfpFastClick(),b.arrowRight=b.arrowLeft=null})},next:function(){b.direction=!0,b.index=C(b.index+1),b.updateItemHTML()},prev:function(){b.direction=!1,b.index=C(b.index-1),b.updateItemHTML()},goTo:function(a){b.direction=a>=b.index,b.index=a,b.updateItemHTML()},preloadNearbyImages:function(){var a,c=b.st.gallery.preload,d=Math.min(c[0],b.items.length),e=Math.min(c[1],b.items.length);for(a=1;a<=(b.direction?e:d);a++)b._preloadItem(b.index+a);for(a=1;a<=(b.direction?d:e);a++)b._preloadItem(b.index-a)},_preloadItem:function(c){if(c=C(c),!b.items[c].preloaded){var d=b.items[c];d.parsed||(d=b.parseEl(c)),m("LazyLoad",d),"image"===d.type&&(d.img=a('<img class="mfp-img" />').on("load.mfploader",function(){d.hasSize=!0}).on("error.mfploader",function(){d.hasSize=!0,d.loadError=!0,m("LazyLoadError",d)}).attr("src",d.src)),d.preloaded=!0}}}});a.magnificPopup.registerModule("retina",{options:{replaceSrc:function(a){return a.src.replace(/\.\w+$/,function(a){return"@2x"+a})},ratio:1},proto:{initRetina:function(){if(window.devicePixelRatio>1){var a=b.st.retina,c=a.ratio;c=isNaN(c)?c():c,c>1&&(k("ImageHasSize.retina",function(a,b){b.img.css({"max-width":b.img[0].naturalWidth/c,width:"100%"})}),k("ElementParse.retina",function(b,d){d.src=a.replaceSrc(d,c)}))}}}}),function(){var b="ontouchstart"in window,c=function(){j.off("touchmove"+d+" touchend"+d)},d=".mfpFastClick";a.fn.mfpFastClick=function(e){return a(this).each(function(){var f,g=a(this);if(b){var h,i,k,l,m,n;g.on("touchstart"+d,function(a){l=!1,n=1,m=a.originalEvent?a.originalEvent.touches[0]:a.touches[0],i=m.clientX,k=m.clientY,j.on("touchmove"+d,function(a){m=a.originalEvent?a.originalEvent.touches:a.touches,n=m.length,m=m[0],(Math.abs(m.clientX-i)>10||Math.abs(m.clientY-k)>10)&&(l=!0,c())}).on("touchend"+d,function(a){c(),l||n>1||(f=!0,a.preventDefault(),clearTimeout(h),h=setTimeout(function(){f=!1},1e3),e())})})}g.on("click"+d,function(){f||e()})})},a.fn.destroyMfpFastClick=function(){a(this).off("touchstart"+d+" click"+d),b&&j.off("touchmove"+d+" touchend"+d)}}(),o()}),"function"!=typeof Object.create&&(Object.create=function(a){function b(){}return b.prototype=a,new b}),function(a,b,c,d){var e={init:function(b,c){var d=this;d.elem=c,d.$elem=a(c),d.options=a.extend({},a.fn.rtTab.options,b),d.rtTabs()},rtTabs:function(){var c=this,d=c.options.activeTab;if(c.$elem.find("li:nth-child("+d+")").addClass("active"),c.rtTabContent(activeTabContent="yes"),c.rtClick(),!0==("false"!==c.$elem.attr("data-hash"))){var e=b.location.hash;e&&c.$elem.find("li").find('a[href="'+e+'"]').trigger("click"),a(b).on("hashchange",function(){var a=b.location.hash;c.$elem.find("li").find('a[href="'+a+'"]').trigger("click")})}},rtClick:function(){var c=this,d=c.$elem.find("li");d.find("a").on("click",function(e){e.preventDefault(),d.removeClass("active"),c.rtTabContent(),a(this).parent().addClass("active");var f=a(this).attr("href");if(a(f).removeClass("hide"),1==("false"!==c.$elem.attr("data-hash"))){var g=a(b).scrollTop();location.hash=a(this).attr("href"),a(b).scrollTop(g)}"function"==typeof c.options.onComplete&&c.options.onComplete.apply(c.elem,arguments)})},rtTabContent:function(b){this.$elem.find("li").find("a").each(function(){var c=a(this),d=c.attr("href");"yes"===b?c.parent().hasClass("active")||a(d).addClass("hide"):a(d).addClass("hide")})}};a.fn.rtTab=function(b){return this.each(function(){var c=Object.create(e);c.init(b,this),a.data(this,"rtTab",c)})},a.fn.rtTab.options={activeTab:1,onComplete:null}}(jQuery,window,document);var rtMagnificPopup,rtm_masonry_container,comment_media=!1,rtMediaHook={hooks:[],is_break:!1,register:function(a,b){void 0===rtMediaHook.hooks[a]&&(rtMediaHook.hooks[a]=[]),rtMediaHook.hooks[a].push(b)},call:function(a,arguments){if(void 0!==rtMediaHook.hooks[a])for(i=0;i<rtMediaHook.hooks[a].length;++i)if(1!=rtMediaHook.hooks[a][i](arguments))return rtMediaHook.is_break=!0,!1;return!0}};jQuery("document").ready(function(a){function b(){if(jQuery("#rtmedia-media-view-form").length>0){var a=jQuery("#rtmedia-media-view-form").attr("action");jQuery.post(a,{},function(a){})}}function c(){var a=jQuery.magnificPopup.instance,b=a.probablyMobile,c=e("rtmedia-touch-swipe-tooltip");b&&""===c?(jQuery("#mobile-swipe-overlay").show(),jQuery("#mobile-swipe-overlay").on("click",function(a){d("rtmedia-touch-swipe-tooltip",!0,365),jQuery(this).hide(),jQuery("#rtmedia-single-media-container .mejs-playpause-button").trigger("click")}),jQuery("#mobile-swipe-overlay").swipe({swipe:function(a,b,c,e,f,g){d("rtmedia-touch-swipe-tooltip",!0,365),jQuery("#mobile-swipe-overlay").hide(),jQuery("#rtmedia-single-media-container .mejs-playpause-button").trigger("click")},threshold:0})):jQuery("#rtmedia-single-media-container .mejs-playpause-button").trigger("click"),jQuery(".mfp-arrow-right").on("click",function(b){a.next()}),jQuery(".mfp-arrow-left").on("click",function(b){a.prev()}),jQuery(".mfp-content .rtmedia-media").swipe({swipeLeft:function(b,c,d,e,f){a.next()},
|
7 |
-
swipeRight:function(b,c,d,e,f){a.prev()},threshold:0})}function d(a,b,c){var d=new Date;d.setTime(d.getTime()+24*c*60*60*1e3);var e="expires="+d.toUTCString();document.cookie=a+"="+b+";"+e+";path=/"}function e(a){for(var b=a+"=",c=document.cookie.split(";"),d=0;d<c.length;d++){for(var e=c[d];" "==e.charAt(0);)e=e.substring(1);if(0==e.indexOf(b))return e.substring(b.length,e.length)}return""}function f(){jQuery(".mfp-arrow-right").hide(),jQuery(".mfp-arrow-left").hide(),jQuery(document).unbind("keydown")}function g(){rtmedia_disable_popup_navigation("#comment_content")}function h(){jQuery(".rtmedia-container").on("click",".rtmedia-delete-media",function(a){a.preventDefault(),confirm(rtmedia_media_delete_confirmation)&&jQuery(this).closest("form").submit()})}jQuery(document).ajaxComplete(function(a,b,c){if("legacy"!==bp_template_pack&&bp_template_pack){var d=get_parameter("action",c.data);"activity_filter"!==d&&"post_update"!==d&&"get_single_activity_content"!==d&&"activity_get_older_updates"!==d||"undefined"==typeof rtmedia_masonry_layout||"true"!==rtmedia_masonry_layout||"undefined"==typeof rtmedia_masonry_layout_activity||"true"!==rtmedia_masonry_layout_activity?"activity_filter"!==d&&"post_update"!==d&&"get_single_activity_content"!==d&&"activity_get_older_updates"!==d||setTimeout(function(){apply_rtMagnificPopup(".rtmedia-list-media.rtm-gallery-list, .rtmedia-activity-container ul.rtmedia-list, #bp-media-list,.bp-media-sc-list, li.media.album_updated ul,ul.bp-media-list-media, li.activity-item div.activity-content div.activity-inner div.bp_media_content, .rtm-bbp-container, ul.rtm-comment-container"),rtmedia_activity_stream_comment_media()},1e3):setTimeout(function(){apply_rtMagnificPopup(".rtmedia-list-media.rtm-gallery-list, .rtmedia-activity-container ul.rtmedia-list, #bp-media-list,.bp-media-sc-list, li.media.album_updated ul,ul.bp-media-list-media, li.activity-item div.activity-content div.activity-inner div.bp_media_content, .rtm-bbp-container, ul.rtm-comment-container"),rtmedia_activity_masonry(),rtmedia_activity_stream_comment_media()},1e3)}}),jQuery(".rtmedia-uploader-div").css({opacity:"1",display:"block",visibility:"visible"}),jQuery(" #whats-new-options ").css({opacity:"1"}),void 0!==a.fn.rtTab&&a(".rtm-tabs").rtTab(),jQuery(".rtmedia-modal-link").length>0&&a(".rtmedia-modal-link").magnificPopup({type:"inline",midClick:!0,closeBtnInside:!0}),a("#rt_media_comment_form").submit(function(b){return""!=a.trim(a("#comment_content").val())||(0==jQuery("#rtmedia-single-media-container").length?rtmedia_gallery_action_alert_message(rtmedia_empty_comment_msg,"warning"):rtmedia_single_media_alert_message(rtmedia_empty_comment_msg,"warning"),!1)}),a("li.rtmedia-list-item p a").each(function(b){a(this).addClass("no-popup")}),a("li.rtmedia-list-item p a").each(function(b){a(this).addClass("no-popup")}),"undefined"!=typeof rtmedia_lightbox_enabled&&"1"==rtmedia_lightbox_enabled&&apply_rtMagnificPopup(".rtmedia-list-media.rtm-gallery-list, .rtmedia-activity-container ul.rtmedia-list, #bp-media-list,.bp-media-sc-list, li.media.album_updated ul,ul.bp-media-list-media, li.activity-item div.activity-content div.activity-inner div.bp_media_content, .rtm-bbp-container, ul.rtm-comment-container"),jQuery.ajaxPrefilter(function(a,b,c){try{if(null==b.data||void 0===b.data||void 0===b.data.action)return!0}catch(a){return!0}if("activity_get_older_updates"==b.data.action){var d=b.success;a.success=function(a){"function"==typeof d&&d(a),apply_rtMagnificPopup(".rtmedia-activity-container ul.rtmedia-list, #bp-media-list, .bp-media-sc-list, li.media.album_updated ul,ul.bp-media-list-media, li.activity-item div.activity-content div.activity-inner div.bp_media_content"),rtMediaHook.call("rtmedia_js_after_activity_added",[])}}else if("get_single_activity_content"==b.data.action){var d=b.success;a.success=function(a){"function"==typeof d&&d(a),setTimeout(function(){apply_rtMagnificPopup(".rtmedia-activity-container ul.rtmedia-list, #bp-media-list, .bp-media-sc-list, li.media.album_updated ul,ul.bp-media-list-media, li.activity-item div.activity-content div.activity-inner div.bp_media_content"),jQuery("ul.activity-list li.rtmedia_update:first-child .wp-audio-shortcode, ul.activity-list li.rtmedia_update:first-child .wp-video-shortcode").mediaelementplayer({classPrefix:"mejs-",defaultVideoWidth:480,defaultVideoHeight:270})},900)}}}),jQuery.ajaxPrefilter(function(a,b,c){try{if(null==b.data||void 0===b.data||void 0===b.data.action)return!0}catch(a){return!0}if("activity_get_older_updates"==b.data.action){var d=b.success;a.success=function(a){"function"==typeof d&&d(a),apply_rtMagnificPopup(".rtmedia-activity-container ul.rtmedia-list, #bp-media-list, .bp-media-sc-list, li.media.album_updated ul,ul.bp-media-list-media, li.activity-item div.activity-content div.activity-inner div.bp_media_content"),jQuery("ul.activity-list li.rtmedia_update div.rtmedia-item-thumbnail > audio.wp-audio-shortcode, ul.activity-list li.rtmedia_update div.rtmedia-item-thumbnail > video.wp-video-shortcode").mediaelementplayer({classPrefix:"mejs-",defaultVideoWidth:480,defaultVideoHeight:270}),setTimeout(function(){rtmedia_activity_stream_comment_media()},900),rtMediaHook.call("rtmedia_js_after_activity_added",[])}}}),jQuery(".rtmedia-container").on("click",".select-all",function(a){jQuery(this).toggleClass("unselect-all").toggleClass("select-all"),jQuery(this).attr("title",rtmedia_unselect_all_visible),jQuery(".rtmedia-list input").each(function(){jQuery(this).prop("checked",!0)}),jQuery(".rtmedia-list-item").addClass("bulk-selected")}),jQuery(".rtmedia-container").on("click",".unselect-all",function(a){jQuery(this).toggleClass("select-all").toggleClass("unselect-all"),jQuery(this).attr("title",rtmedia_select_all_visible),jQuery(".rtmedia-list input").each(function(){jQuery(this).prop("checked",!1)}),jQuery(".rtmedia-list-item").removeClass("bulk-selected")}),jQuery(".rtmedia-container").on("click",".rtmedia-move",function(a){jQuery(".rtmedia-delete-container").slideUp(),jQuery(".rtmedia-move-container").slideToggle()}),jQuery("#rtmedia-create-album-modal").on("click","#rtmedia_create_new_album",function(b){if($albumname=jQuery("<span/>").text(jQuery.trim(jQuery("#rtmedia_album_name").val())).html(),$album_description=jQuery("#rtmedia_album_description"),$context=jQuery.trim(jQuery("#rtmedia_album_context").val()),$context_id=jQuery.trim(jQuery("#rtmedia_album_context_id").val()),$privacy=jQuery.trim(jQuery("#rtmedia_select_album_privacy").val()),$create_album_nonce=jQuery.trim(jQuery("#rtmedia_create_album_nonce").val()),""!=$albumname){var c={action:"rtmedia_create_album",name:$albumname,description:$album_description.val(),context:$context,context_id:$context_id,create_album_nonce:$create_album_nonce};""!==$privacy&&(c.privacy=$privacy),a("#rtmedia_create_new_album").attr("disabled","disabled");var d=a("#rtmedia_create_new_album").html();a("#rtmedia_create_new_album").prepend("<img src='"+rMedia_loading_file+"' />"),jQuery.post(rtmedia_ajax_url,c,function(b){if(void 0!==b.album){b=jQuery.trim(b.album);var c=!0;$album_description.val(""),a("#rtmedia_album_name").focus(),jQuery(".rtmedia-user-album-list").each(function(){if(jQuery(this).children("optgroup").each(function(){if(jQuery(this).attr("value")===$context)return c=!1,void jQuery(this).append('<option value="'+b+'">'+$albumname+"</option>")}),c){var a=$context.charAt(0).toUpperCase()+$context.slice(1)+" "+rtmedia_main_js_strings.rtmedia_albums,d='<optgroup value="'+$context+'" label="'+a+'"><option value="'+b+'">'+$albumname+"</option></optgroup>";jQuery(this).append(d)}}),jQuery('select.rtmedia-user-album-list option[value="'+b+'"]').prop("selected",!0),jQuery(".rtmedia-create-new-album-container").slideToggle(),jQuery("#rtmedia_album_name").val(""),jQuery("#rtmedia-create-album-modal").append("<div class='rtmedia-success rtmedia-create-album-alert'><b>"+$albumname+"</b>"+rtmedia_album_created_msg+"</div>"),setTimeout(function(){jQuery(".rtmedia-create-album-alert").remove()},4e3),setTimeout(function(){galleryObj.reloadView(),jQuery(".close-reveal-modal").click()},2e3)}else void 0!==b.error?rtmedia_gallery_action_alert_message(b.error,"warning"):rtmedia_gallery_action_alert_message(rtmedia_something_wrong_msg,"warning");a("#rtmedia_create_new_album").removeAttr("disabled"),a("#rtmedia_create_new_album").html(d)})}else rtmedia_gallery_action_alert_message(rtmedia_empty_album_name_msg,"warning")}),jQuery(".rtmedia-container").on("click",".rtmedia-delete-selected",function(a){jQuery(".rtmedia-list :checkbox:checked").length>0?confirm(rtmedia_selected_media_delete_confirmation)&&jQuery(this).closest("form").attr("action","../../../"+rtmedia_media_slug+"/delete").submit():rtmedia_gallery_action_alert_message(rtmedia_no_media_selected,"warning")}),jQuery(".rtmedia-container").on("click",".rtmedia-move-selected",function(a){jQuery(".rtmedia-list :checkbox:checked").length>0?confirm(rtmedia_selected_media_move_confirmation)&&jQuery(this).closest("form").attr("action","").submit():rtmedia_gallery_action_alert_message(rtmedia_no_media_selected,"warning")}),jQuery("#buddypress").on("change",".rtm-activity-privacy-opt",function(){var a=jQuery(this).attr("id");a=a.split("-"),a=a[a.length-1];var b=this;data={activity_id:a,privacy:jQuery(this).val(),nonce:jQuery("#rtmedia_activity_privacy_nonce").val(),action:"rtm_change_activity_privacy"},jQuery.post(ajaxurl,data,function(a){var c="",d="";"true"==a?(c=rtmedia_main_js_strings.privacy_update_success,d="success"):(c=rtmedia_main_js_strings.privacy_update_error,d="fail"),jQuery(b).after('<p class="rtm-ac-privacy-updated '+d+'">'+c+"</p>"),setTimeout(function(){jQuery(b).siblings(".rtm-ac-privacy-updated").remove()},2e3)})}),jQuery(".media_search_input").on("keyup",function(){rtm_search_media_text_validation()}),b(),rtMediaHook.register("rtmedia_js_popup_after_content_added",function(){b(),h(),mfp=jQuery.magnificPopup.instance,jQuery(mfp.items).size()>1&&0==comment_media?c():f(),g(),rtmedia_disable_popup_navigation_comment_media_focus();var d=a(window).height();jQuery(".rtm-lightbox-container .mejs-video").css({height:.8*d,"over-flow":"hidden"}),jQuery(".mfp-content .rtmedia-media").css({"max-height":.87*d,"over-flow":"hidden"}),rtmedia_init_action_dropdown(".rtm-lightbox-container .rtmedia-actions"),jQuery(".rtmedia-comment-link").on("click",function(a){a.preventDefault(),jQuery("#comment_content").focus()}),jQuery(".rtm-more").shorten({showChars:130});var e=a(".rtm-gallery-title"),i="";""!=(i=a.isEmptyObject(e)?a("#subnav.item-list-tabs li.selected ").html():e.html())&&a(".rtm-ltb-gallery-title .ltb-title").html(i);var j=a("#subnav.item-list-tabs li.selected span").html();return a("li.total").html(j),!0});var i=jQuery("#drag-drop-area"),j=jQuery("#whats-new");i.html();jQuery("#rtmedia-upload-container").after("<div id='rtm-drop-files-title'>"+rtmedia_drop_media_msg+"</div>"),"undefined"!=typeof rtmedia_bp_enable_activity&&"1"==rtmedia_bp_enable_activity&&jQuery("#whats-new-textarea").append("<div id='rtm-drop-files-title'>"+rtmedia_drop_media_msg+"</div>"),jQuery(document).on("dragover",function(a){a.preventDefault(),a.target!=this&&(jQuery("#rtm-media-gallery-uploader").show(),"undefined"!=typeof rtmedia_bp_enable_activity&&"1"==rtmedia_bp_enable_activity&&j.addClass("rtm-drag-drop-active"),i.addClass("rtm-drag-drop-active"),jQuery("#rtm-drop-files-title").show())}).on("dragleave",function(a){if(a.preventDefault(),0!=a.originalEvent.pageX&&0!=a.originalEvent.pageY)return!1;"undefined"!=typeof rtmedia_bp_enable_activity&&"1"==rtmedia_bp_enable_activity&&(j.removeClass("rtm-drag-drop-active"),j.removeAttr("style")),i.removeClass("rtm-drag-drop-active"),jQuery("#rtm-drop-files-title").hide()}).on("drop",function(a){a.preventDefault(),jQuery(".bp-suggestions").focus(),"undefined"!=typeof rtmedia_bp_enable_activity&&"1"==rtmedia_bp_enable_activity&&(j.removeClass("rtm-drag-drop-active"),j.removeAttr("style")),i.removeClass("rtm-drag-drop-active"),jQuery("#rtm-drop-files-title").hide()}),jQuery(".rtmedia-container").on("click",".rtmedia-delete-album",function(a){a.preventDefault(),confirm(rtmedia_album_delete_confirmation)&&jQuery(this).closest("form").submit()}),jQuery(".rtmedia-container").on("click",".rtmedia-delete-media",function(a){a.preventDefault(),confirm(rtmedia_media_delete_confirmation)&&jQuery(this).closest("form").submit()}),rtmedia_init_action_dropdown(""),a(document).click(function(){a(".click-nav ul").is(":visible")&&a(".click-nav ul",this).hide()}),jQuery(".rtmedia-comment-link").on("click",function(a){a.preventDefault(),jQuery("#comment_content").focus()}),jQuery(".rtm-more").length>0&&a(".rtm-more").shorten({showChars:200}),"undefined"!=typeof rtmedia_masonry_layout&&"true"==rtmedia_masonry_layout&&"undefined"!=typeof rtmedia_masonry_layout_activity&&"true"==rtmedia_masonry_layout_activity&&rtmedia_activity_masonry(),jQuery(document).ajaxComplete(function(a,b,c){var d=get_parameter("action",c.data);"post_update"!==d&&"get_single_activity_content"!==d&&"activity_get_older_updates"!==d||"undefined"==typeof rtmedia_masonry_layout||"true"!=rtmedia_masonry_layout||"undefined"==typeof rtmedia_masonry_layout_activity||"true"!=rtmedia_masonry_layout_activity||rtmedia_activity_masonry()}),"undefined"!=typeof rtmedia_masonry_layout&&"true"==rtmedia_masonry_layout&&0==jQuery(".rtmedia-container .rtmedia-list.rtm-no-masonry").length&&(rtm_masonry_container=jQuery(".rtmedia-container .rtmedia-list"),rtm_masonry_container.masonry({itemSelector:".rtmedia-list-item"}),setInterval(function(){jQuery.each(jQuery(".rtmedia-list.masonry .rtmedia-item-title"),function(a,b){jQuery(b).width(jQuery(b).siblings(".rtmedia-item-thumbnail").children("img").width())}),rtm_masonry_reload(rtm_masonry_container)},1e3),jQuery.each(jQuery(".rtmedia-list.masonry .rtmedia-item-title"),function(a,b){jQuery(b).width(jQuery(b).siblings(".rtmedia-item-thumbnail").children("img").width())})),jQuery(".rtm-uploader-tabs").length>0&&jQuery(".rtm-uploader-tabs li").click(function(a){jQuery(this).hasClass("active")||(jQuery(this).siblings().removeClass("active"),jQuery(this).parents(".rtm-uploader-tabs").siblings().hide(),class_name=jQuery(this).attr("class"),jQuery(this).parents(".rtm-uploader-tabs").siblings('[data-id="'+class_name+'"]').show(),jQuery(this).addClass("active"),"rtm-upload-tab"!=class_name?jQuery("div.moxie-shim").hide():jQuery("div.moxie-shim").show())}),jQuery(".rtmedia-container").on("click",".rtm-delete-media",function(a){a.preventDefault();var b="Are you sure you want to delete this media?";if("undefined"!=typeof rtmedia_media_delete_confirmation&&(b=rtmedia_media_delete_confirmation),confirm(b)){var c=jQuery(this).closest("li"),d=jQuery("#rtmedia_media_delete_nonce").val(),e={action:"delete_uploaded_media",nonce:d,media_id:c.attr("id")};jQuery.ajax({url:ajaxurl,type:"post",data:e,success:function(a){"1"==a?(rtmedia_gallery_action_alert_message(rtmedia_main_js_strings.file_delete_success,"success"),c.remove(),"undefined"!=typeof rtmedia_masonry_layout&&"true"==rtmedia_masonry_layout&&0==jQuery(".rtmedia-container .rtmedia-list.rtm-no-masonry").length&&rtm_masonry_reload(rtm_masonry_container)):rtmedia_gallery_action_alert_message(rtmedia_file_not_deleted,"warning")}})}})}),function(a){a.fn.shorten=function(b){"use strict";var c={showChars:100,minHideChars:10,ellipsesText:"...",moreText:rtmedia_read_more,lessText:rtmedia__show_less,onLess:function(){},onMore:function(){},errMsg:null,force:!1};return b&&a.extend(c,b),!(a(this).data("jquery.shorten")&&!c.force)&&(a(this).data("jquery.shorten",!0),a(document).off("click",".morelink"),a(document).on({click:function(){var b=a(this);return b.hasClass("less")?(b.removeClass("less"),b.html(c.moreText),b.parent().prev().hide(0,function(){b.parent().prev().prev().show()}).hide(0,function(){c.onLess()})):(b.addClass("less"),b.html(c.lessText),b.parent().prev().show(0,function(){b.parent().prev().prev().hide()}).show(0,function(){c.onMore()})),!1}},".morelink"),this.each(function(){var b=a(this),d=b.html();if(b.text().length>c.showChars+c.minHideChars){var e=d.substr(0,c.showChars);if(e.indexOf("<")>=0){for(var f=!1,g="",h=0,i=[],k=null,l=0,m=0;m<=c.showChars;l++)if("<"!=d[l]||f||(f=!0,k=d.substring(l+1,d.indexOf(">",l)),"/"==k[0]?k!="/"+i[0]?c.errMsg="ERROR en HTML: the top of the stack should be the tag that closes":i.shift():"br"!=k.toLowerCase()&&i.unshift(k)),f&&">"==d[l]&&(f=!1),f)g+=d.charAt(l);else if(m++,h<=c.showChars)g+=d.charAt(l),h++;else if(i.length>0){for(j=0;j<i.length;j++)g+="</"+i[j]+">";break}e=a("<div/>").html(g+'<span class="ellip">'+c.ellipsesText+"</span>").html()}else e+=c.ellipsesText;var n='<div class="shortcontent">'+e+'</div><div class="allcontent">'+d+'</div><span><a href="javascript://nop/" class="morelink">'+c.moreText+"</a></span>";b.html(n),b.find(".allcontent").hide(),a(".shortcontent p:last",b).css("margin-bottom",0)}}))}}(jQuery),window.onload=function(){"undefined"!=typeof rtmedia_masonry_layout&&"true"==rtmedia_masonry_layout&&0==jQuery(".rtmedia-container .rtmedia-list.rtm-no-masonry").length&&rtm_masonry_reload(rtm_masonry_container),rtm_search_media_text_validation(),check_condition("search")&&jQuery("#media_search_remove").show()},jQuery(document).ready(function(){rtm_upload_terms_activity()});
|
3 |
* @package rtMedia
|
4 |
*/
|
5 |
|
6 |
+
function apply_rtMagnificPopup(a){jQuery("document").ready(function(b){var c="";if(c="undefined"==typeof rtmedia_load_more?"Loading media":rtmedia_load_more,"undefined"!=typeof rtmedia_lightbox_enabled&&"1"==rtmedia_lightbox_enabled){var d,e,f=!1;b(".activity-item .rtmedia-activity-container .rtmedia-list-item > a").siblings("p").children("a").length>0&&b(".activity-item .rtmedia-activity-container .rtmedia-list-item > a").siblings("p").children("a").addClass("no-popup"),rtMagnificPopup=jQuery(a).magnificPopup({delegate:"a:not(.no-popup, .mejs-time-slider, .mejs-volume-slider, .mejs-horizontal-volume-slider)",type:"ajax",fixedContentPos:!0,fixedBgPos:!0,tLoading:c+" #%curr%...",mainClass:"mfp-img-mobile",preload:[1,3],closeOnBgClick:!0,gallery:{enabled:!0,navigateByImgClick:!0,arrowMarkup:"",preload:[0,1]},image:{tError:'<a href="%url%">The image #%curr%</a> could not be loaded.',titleSrc:function(a){return a.el.attr("title")+"<small>by Marsel Van Oosten</small>"}},callbacks:{ajaxContentAdded:function(){a=jQuery.magnificPopup.instance,1===jQuery(a.items).size()&&jQuery(".mfp-arrow").remove();var a=jQuery.magnificPopup.instance,c=a.currItem.el,g=c.parent();if(g.is("li")||(g=g.parent()),(g.is(":nth-last-child(2)")||g.is(":last-child"))&&g.find("a").hasClass("rtmedia-list-item-a")){g.next();"block"==jQuery("#rtMedia-galary-next").css("display")&&(f||(d=a.ev.children(),f=!0,e=nextpage),jQuery("#rtMedia-galary-next").click())}var h=a.items.length;if(a.index==h-1&&!g.is(":last-child"))return void c.click();var i={};"undefined"!=typeof _wpmejsSettings&&(i.pluginPath=_wpmejsSettings.pluginPath);var j=jQuery(".rtmedia-container .rtmedia-single-meta").height(),k=!1;void 0!==a&&void 0!==a.probablyMobile&&1==a.probablyMobile&&(k=!0),b(".mfp-content .rtmedia-single-media .wp-audio-shortcode,.mfp-content .rtmedia-single-media .wp-video-shortcode,.mfp-content .rtmedia-single-media .bp_media_content video").attr("autoplay",!0),k&&b(".mfp-content .rtmedia-single-media .wp-video-shortcode,.mfp-content .rtmedia-single-media .bp_media_content video").attr("muted",!1),b(".mfp-content .rtmedia-single-media .wp-audio-shortcode,.mfp-content .rtmedia-single-media .wp-video-shortcode,.mfp-content .rtmedia-single-media .bp_media_content video").mediaelementplayer({classPrefix:"mejs-",defaultVideoWidth:480,hideVolumeOnTouchDevices:!1,features:["playpause","progress","current","volume","fullscreen"],defaultVideoHeight:270,alwaysShowControls:k,enableAutosize:!0,clickToPlayPause:!0,videoHeight:-1,success:function(a,c){a.addEventListener("loadeddata",function(c){var d=b(a).height(),e=b(window).height(),f=jQuery("div.rtm-ltb-action-container").height(),f=f+50,g=j-f;d>e&&jQuery(".rtmedia-container #rtmedia-single-media-container .mejs-container").attr("style","height:"+g+"px !important; transition:0.2s")},!1),k&&b(a).hasClass("wp-video-shortcode")?jQuery("body").on("touchstart",".mejs-overlay-button",function(b){a.paused?a.play():a.pause()}):a.pause()}}),b(".mfp-content .mejs-audio .mejs-controls").css("position","relative"),rtMediaHook.call("rtmedia_js_popup_after_content_added",[]),"undefined"!=typeof bp&&void 0!==bp.mentions&&void 0!==bp.mentions.users&&(b("#atwho-container #atwho-ground-comment_content").remove(),b("#comment_content").bp_mentions(bp.mentions.users)),rtmedia_reset_video_and_audio_for_popup(),apply_rtMagnificPopup(".rtmedia-list-media.rtm-gallery-list, .rtmedia-activity-container ul.rtmedia-list, #bp-media-list,.bp-media-sc-list, li.media.album_updated ul,ul.bp-media-list-media, li.activity-item div.activity-content div.activity-inner div.bp_media_content, .rtm-bbp-container, ul.rtm-comment-container")},open:function(){var a=jQuery(".mfp-bg"),b=jQuery(".mfp-wrap");a.height(a.height()+b.height())},close:function(a){f&&(mfp.ev.empty(),mfp.ev.append(d),nextpage=e,f=!1,nextpage>1&&jQuery("#rtMedia-galary-next").show()),rtmedia_single_page_popup_close()},BeforeChange:function(a){}}})}jQuery(document).ajaxComplete(function(){jQuery("[id^=imgedit-leaving]").filter(function(){var a=jQuery(this).text();jQuery(this).text(a.replace("OK","Save"))})})})}function rtmedia_init_action_dropdown(a){var b,c;jQuery(a+" .click-nav > span,"+a+" .click-nav > div").toggleClass("no-js js"),jQuery(a+" .click-nav .js ul").hide(),jQuery(a+" .click-nav .clicker").click(function(a){b=jQuery("#rtm-media-options .click-nav .clicker").next("ul"),c=jQuery(this).next("ul"),jQuery.each(b,function(a,b){jQuery(b).html()!=c.html()&&jQuery(b).hide()}),jQuery(c).toggle(),a.stopPropagation()})}function bp_media_create_element(a){return!1}function rtmedia_version_compare(a,b){if(typeof a+typeof b!="stringstring")return!1;for(var c=a.split("."),d=b.split("."),e=0,f=Math.max(c.length,d.length);e<f;e++){if(c[e]&&!d[e]&&parseInt(c[e])>0||parseInt(c[e])>parseInt(d[e]))return!0;if(d[e]&&!c[e]&&parseInt(d[e])>0||parseInt(c[e])<parseInt(d[e]))return!1}return!0}function rtm_is_element_exist(a){return jQuery(a).length>0}function rtm_masonry_reload(a){setTimeout(function(){a.masonry("reload")},250)}function rtm_search_media_text_validation(){""===jQuery("#media_search_input").val()?jQuery("#media_search").css("cursor","not-allowed"):jQuery("#media_search").css("cursor","pointer")}function rtmediaGetParameterByName(a){a=a.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]");var b=new RegExp("[\\?&]"+a+"=([^&#]*)"),c=b.exec(location.search);return null==c?"":decodeURIComponent(c[1].replace(/\+/g," "))}function rtmedia_single_media_alert_message(a,b,c){var d="rtmedia-success";"warning"==b&&(d="rtmedia-warning");var e=!1;jQuery(".rtmedia-message-container").each(function(a,b){return b=jQuery(b),c&&b.hasClass("rtmedia-empty-comment-error-class")?(b.remove(),e=!0,!1):void 0!==c||b.hasClass("rtmedia-empty-comment-error-class")?void 0:(b.remove(),e=!0,!1)});var f=jQuery("<div>",{title:"Click to dismiss",class:"rtmedia-message-container"+(c?" rtmedia-empty-comment-error-class":""),style:"margin:1em 0;"}),g=jQuery("<span>",{class:d});g.html(a),g.appendTo(f);var h;c?(h=jQuery("#rt_media_comment_form"),jQuery("#comment_content").focus()):void 0===c&&(h=jQuery(".rtmedia-single-media .rtmedia-media"),h.css("opacity","0.2")),h.after(f),e&&(g.css({border:"2px solid #884646"}),setTimeout(function(){g.css({border:"none"})},500)),setTimeout(function(){f.remove(),void 0===c&&h.css("opacity","1")},3e3),f.click(function(){f.remove(),void 0===c&&h.css("opacity","1")})}function rtmedia_gallery_action_alert_message(a,b){var c="rtmedia-success";"warning"==b&&(c="rtmedia-warning");jQuery("body").append('<div class="rtmedia-gallery-alert-container"> </div>'),jQuery(".rtmedia-gallery-alert-container").append("<div class='rtmedia-gallery-message-box'><span class='"+c+"'>"+a+" </span></div>"),setTimeout(function(){jQuery(".rtmedia-gallery-alert-container").remove()},3e3),jQuery(".rtmedia-gallery-message-box").click(function(){jQuery(".rtmedia-gallery-alert-container").remove()})}function rtmedia_activity_masonry(){jQuery("#activity-stream .rtmedia-activity-container .rtmedia-list").masonry({itemSelector:".rtmedia-list-item",gutter:7});var a=0,b=setInterval(function(){a+=1,5===a&&clearInterval(b),jQuery.each(jQuery(".rtmedia-activity-container .rtmedia-list.masonry .rtmedia-item-title"),function(a,b){jQuery(b).width(jQuery(b).siblings(".rtmedia-item-thumbnail").children("img").width())}),rtm_masonry_reload(jQuery("#activity-stream .rtmedia-activity-container .rtmedia-list"))},1e3)}function get_parameter(a,b){if(!a)return!1;b||(b=window.location.href);var a=a.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]"),c=a+"=([^&#]*)",d=new RegExp(c),e=d.exec(b);return null!==e&&e[1]}function rtm_upload_terms_activity(){if(jQuery("#rtmedia_upload_terms_conditions").length>0){jQuery("#bp-nouveau-activity-form").on("click","#aw-whats-new-submit",function(a){var b=jQuery("#whats-new-form"),c=b.find("#rtmedia_upload_terms_conditions");if(0!==c.length&&!1===c.prop("checked")&&0===b.find("#message").length){a.preventDefault();var d=b.find(".rtmedia-upload-terms");rtp_display_terms_warning(d,rtmedia_upload_terms_check_terms_message)}});var a=jQuery("#whats-new-form");a.length>0&&jQuery("#whats-new-form, #rtmedia_upload_terms_conditions").on("click",function(b){a.find("input:hidden").each(function(){jQuery(this).prop("disabled",!1)})})}}!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):window.jQuery||window.Zepto)}(function(a){var b,c,d,e,f,g,h=function(){},i=!!window.jQuery,j=a(window),k=function(a,c){b.ev.on("mfp"+a+".mfp",c)},l=function(b,c,d,e){var f=document.createElement("div");return f.className="mfp-"+b,d&&(f.innerHTML=d),e?c&&c.appendChild(f):(f=a(f),c&&f.appendTo(c)),f},m=function(c,d){b.ev.triggerHandler("mfp"+c,d),b.st.callbacks&&(c=c.charAt(0).toLowerCase()+c.slice(1),b.st.callbacks[c]&&b.st.callbacks[c].apply(b,a.isArray(d)?d:[d]))},n=function(c){return c===g&&b.currTemplate.closeBtn||(b.currTemplate.closeBtn=a(b.st.closeMarkup.replace("%title%",b.st.tClose)),g=c),b.currTemplate.closeBtn},o=function(){a.magnificPopup.instance||(b=new h,b.init(),a.magnificPopup.instance=b)},p=function(){var a=document.createElement("p").style,b=["ms","O","Moz","Webkit"];if(void 0!==a.transition)return!0;for(;b.length;)if(b.pop()+"Transition"in a)return!0;return!1};h.prototype={constructor:h,init:function(){var c=navigator.appVersion;b.isIE7=-1!==c.indexOf("MSIE 7."),b.isIE8=-1!==c.indexOf("MSIE 8."),b.isLowIE=b.isIE7||b.isIE8,b.isAndroid=/android/gi.test(c),b.isIOS=/iphone|ipad|ipod/gi.test(c),b.supportsTransition=p(),b.probablyMobile=b.isAndroid||b.isIOS||/(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent),d=a(document),b.popupsCache={}},open:function(c){var e;if(!1===c.isObj){b.items=c.items.toArray(),b.index=0;var g,h=c.items;for(e=0;e<h.length;e++)if(g=h[e],g.parsed&&(g=g.el[0]),g===c.el[0]){b.index=e;break}}else b.items=a.isArray(c.items)?c.items:[c.items],b.index=c.index||0;if(b.isOpen)return void b.updateItemHTML();b.types=[],f="",c.mainEl&&c.mainEl.length?b.ev=c.mainEl.eq(0):b.ev=d,c.key?(b.popupsCache[c.key]||(b.popupsCache[c.key]={}),b.currTemplate=b.popupsCache[c.key]):b.currTemplate={},b.st=a.extend(!0,{},a.magnificPopup.defaults,c),b.fixedContentPos="auto"===b.st.fixedContentPos?!b.probablyMobile:b.st.fixedContentPos,b.st.modal&&(b.st.closeOnContentClick=!1,b.st.closeOnBgClick=!1,b.st.showCloseBtn=!1,b.st.enableEscapeKey=!1),b.bgOverlay||(b.bgOverlay=l("bg").on("click.mfp",function(){b.close()}),b.wrap=l("wrap").attr("tabindex",-1).on("click.mfp",function(a){b._checkIfClose(a.target)&&b.close()}),b.container=l("container",b.wrap)),b.contentContainer=l("content"),b.st.preloader&&(b.preloader=l("preloader",b.container,b.st.tLoading));var i=a.magnificPopup.modules;for(e=0;e<i.length;e++){var o=i[e];o=o.charAt(0).toUpperCase()+o.slice(1),b["init"+o].call(b)}m("BeforeOpen"),b.st.showCloseBtn&&(b.st.closeBtnInside?(k("MarkupParse",function(a,b,c,d){c.close_replaceWith=n(d.type)}),f+=" mfp-close-btn-in"):b.wrap.append(n())),b.st.alignTop&&(f+=" mfp-align-top"),b.fixedContentPos?b.wrap.css({overflow:b.st.overflowY,overflowX:"hidden",overflowY:b.st.overflowY}):b.wrap.css({top:j.scrollTop(),position:"absolute"}),(!1===b.st.fixedBgPos||"auto"===b.st.fixedBgPos&&!b.fixedContentPos)&&b.bgOverlay.css({height:d.height(),position:"absolute"}),b.st.enableEscapeKey&&d.on("keyup.mfp",function(a){27===a.keyCode&&b.close()}),j.on("resize.mfp",function(){b.updateSize()}),b.st.closeOnContentClick||(f+=" mfp-auto-cursor"),f&&b.wrap.addClass(f);var p=b.wH=j.height(),q={};if(b.fixedContentPos&&b._hasScrollBar(p)){var r=b._getScrollbarSize();r&&(q.marginRight=r)}b.fixedContentPos&&(b.isIE7?a("body, html").css("overflow","hidden"):q.overflow="hidden");var s=b.st.mainClass;return b.isIE7&&(s+=" mfp-ie7"),s&&b._addClassToMFP(s),b.updateItemHTML(),m("BuildControls"),a("html").css(q),b.bgOverlay.add(b.wrap).prependTo(b.st.prependTo||a(document.body)),b._lastFocusedEl=document.activeElement,setTimeout(function(){b.content?(b._addClassToMFP("mfp-ready"),b._setFocus()):b.bgOverlay.addClass("mfp-ready"),d.on("focusin.mfp",b._onFocusIn)},16),b.isOpen=!0,b.updateSize(p),m("Open"),c},close:function(){b.isOpen&&(m("BeforeClose"),b.isOpen=!1,b.st.removalDelay&&!b.isLowIE&&b.supportsTransition?(b._addClassToMFP("mfp-removing"),setTimeout(function(){b._close()},b.st.removalDelay)):b._close())},_close:function(){m("Close");var c="mfp-removing mfp-ready ";if(b.bgOverlay.detach(),b.wrap.detach(),b.container.empty(),b.st.mainClass&&(c+=b.st.mainClass+" "),b._removeClassFromMFP(c),b.fixedContentPos){var e={marginRight:""};b.isIE7?a("body, html").css("overflow",""):e.overflow="",a("html").css(e)}d.off("keyup.mfp focusin.mfp"),b.ev.off(".mfp"),b.wrap.attr("class","mfp-wrap").removeAttr("style"),b.bgOverlay.attr("class","mfp-bg"),b.container.attr("class","mfp-container"),!b.st.showCloseBtn||b.st.closeBtnInside&&!0!==b.currTemplate[b.currItem.type]||b.currTemplate.closeBtn&&b.currTemplate.closeBtn.detach(),b._lastFocusedEl&&a(b._lastFocusedEl).focus(),b.currItem=null,b.content=null,b.currTemplate=null,b.prevHeight=0,m("AfterClose")},updateSize:function(a){if(b.isIOS){var c=document.documentElement.clientWidth/window.innerWidth,d=window.innerHeight*c;b.wrap.css("height",d),b.wH=d}else b.wH=a||j.height();b.fixedContentPos||b.wrap.css("height",b.wH),m("Resize")},updateItemHTML:function(){var c=b.items[b.index];b.contentContainer.detach(),b.content&&b.content.detach(),c.parsed||(c=b.parseEl(b.index));var d=c.type;if(m("BeforeChange",[b.currItem?b.currItem.type:"",d]),b.currItem=c,!b.currTemplate[d]){var f=!!b.st[d]&&b.st[d].markup;m("FirstMarkupParse",f),b.currTemplate[d]=!f||a(f)}e&&e!==c.type&&b.container.removeClass("mfp-"+e+"-holder");var g=b["get"+d.charAt(0).toUpperCase()+d.slice(1)](c,b.currTemplate[d]);b.appendContent(g,d),c.preloaded=!0,m("Change",c),e=c.type,b.container.prepend(b.contentContainer),m("AfterChange")},appendContent:function(a,c){b.content=a,a?b.st.showCloseBtn&&b.st.closeBtnInside&&!0===b.currTemplate[c]?b.content.find(".mfp-close").length||b.content.append(n()):b.content=a:b.content="",m("BeforeAppend"),b.container.addClass("mfp-"+c+"-holder"),b.contentContainer.append(b.content)},parseEl:function(c){var d,e=b.items[c];if(e.tagName?e={el:a(e)}:(d=e.type,e={data:e,src:e.src}),e.el){for(var f=b.types,g=0;g<f.length;g++)if(e.el.hasClass("mfp-"+f[g])){d=f[g];break}e.src=e.el.attr("data-mfp-src"),e.src||(e.src=e.el.attr("href"))}return e.type=d||b.st.type||"inline",e.index=c,e.parsed=!0,b.items[c]=e,m("ElementParse",e),b.items[c]},addGroup:function(a,c){var d=function(d){d.mfpEl=this,b._openClick(d,a,c)};c||(c={});var e="click.magnificPopup";c.mainEl=a,c.items?(c.isObj=!0,a.off(e).on(e,d)):(c.isObj=!1,c.delegate?a.off(e).on(e,c.delegate,d):(c.items=a,a.off(e).on(e,d)))},_openClick:function(c,d,e){if((void 0!==e.midClick?e.midClick:a.magnificPopup.defaults.midClick)||2!==c.which&&!c.ctrlKey&&!c.metaKey){var f=void 0!==e.disableOn?e.disableOn:a.magnificPopup.defaults.disableOn;if(f)if(a.isFunction(f)){if(!f.call(b))return!0}else if(j.width()<f)return!0;c.type&&(c.preventDefault(),b.isOpen&&c.stopPropagation()),e.el=a(c.mfpEl),e.delegate&&(e.items=d.find(e.delegate)),b.open(e)}},updateStatus:function(a,d){if(b.preloader){c!==a&&b.container.removeClass("mfp-s-"+c),d||"loading"!==a||(d=b.st.tLoading);var e={status:a,text:d};m("UpdateStatus",e),a=e.status,d=e.text,b.preloader.html(d),b.preloader.find("a").on("click",function(a){a.stopImmediatePropagation()}),b.container.addClass("mfp-s-"+a),c=a}},_checkIfClose:function(c){if(!a(c).hasClass("mfp-prevent-close")){var d=b.st.closeOnContentClick,e=b.st.closeOnBgClick;if(d&&e)return!0;if(!b.content||a(c).hasClass("mfp-close")||b.preloader&&c===b.preloader[0])return!0;if(c===b.content[0]||a.contains(b.content[0],c)){if(d)return!0}else if(e&&a.contains(document,c))return!0;return!1}},_addClassToMFP:function(a){b.bgOverlay.addClass(a),b.wrap.addClass(a)},_removeClassFromMFP:function(a){this.bgOverlay.removeClass(a),b.wrap.removeClass(a)},_hasScrollBar:function(a){return(b.isIE7?d.height():document.body.scrollHeight)>(a||j.height())},_setFocus:function(){(b.st.focus?b.content.find(b.st.focus).eq(0):b.wrap).focus()},_onFocusIn:function(c){if(c.target!==b.wrap[0]&&!a.contains(b.wrap[0],c.target))return b._setFocus(),!1},_parseMarkup:function(b,c,d){var e;d.data&&(c=a.extend(d.data,c)),m("MarkupParse",[b,c,d]),a.each(c,function(a,c){if(void 0===c||!1===c)return!0;if(e=a.split("_"),e.length>1){var d=b.find(".mfp-"+e[0]);if(d.length>0){var f=e[1];"replaceWith"===f?d[0]!==c[0]&&d.replaceWith(c):"img"===f?d.is("img")?d.attr("src",c):d.replaceWith('<img src="'+c+'" class="'+d.attr("class")+'" />'):d.attr(e[1],c)}}else b.find(".mfp-"+a).html(c)})},_getScrollbarSize:function(){if(void 0===b.scrollbarSize){var a=document.createElement("div");a.style.cssText="width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;",document.body.appendChild(a),b.scrollbarSize=a.offsetWidth-a.clientWidth,document.body.removeChild(a)}return b.scrollbarSize}},a.magnificPopup={instance:null,proto:h.prototype,modules:[],open:function(b,c){return o(),b=b?a.extend(!0,{},b):{},b.isObj=!0,b.index=c||0,this.instance.open(b)},close:function(){return a.magnificPopup.instance&&a.magnificPopup.instance.close()},registerModule:function(b,c){c.options&&(a.magnificPopup.defaults[b]=c.options),a.extend(this.proto,c.proto),this.modules.push(b)},defaults:{disableOn:0,key:null,midClick:!1,mainClass:"",preloader:!0,focus:"",closeOnContentClick:!1,closeOnBgClick:!0,closeBtnInside:!0,showCloseBtn:!0,enableEscapeKey:!0,modal:!1,alignTop:!1,removalDelay:0,prependTo:null,fixedContentPos:"auto",fixedBgPos:"auto",overflowY:"auto",closeMarkup:'<button title="%title%" type="button" class="mfp-close">×</button>',tClose:"Close (Esc)",tLoading:"Loading..."}},a.fn.magnificPopup=function(c){o();var d=a(this);if("string"==typeof c)if("open"===c){var e,f=i?d.data("magnificPopup"):d[0].magnificPopup,g=parseInt(arguments[1],10)||0;f.items?e=f.items[g]:(e=d,f.delegate&&(e=e.find(f.delegate)),e=e.eq(g)),b._openClick({mfpEl:e},d,f)}else b.isOpen&&b[c].apply(b,Array.prototype.slice.call(arguments,1));else c=a.extend(!0,{},c),i?d.data("magnificPopup",c):d[0].magnificPopup=c,b.addGroup(d,c);return d};var q,r,s,t=function(){s&&(r.after(s.addClass(q)).detach(),s=null)};a.magnificPopup.registerModule("inline",{options:{hiddenClass:"hide",markup:"",tNotFound:"Content not found"},proto:{initInline:function(){b.types.push("inline"),k("Close.inline",function(){t()})},getInline:function(c,d){if(t(),c.src){var e=b.st.inline,f=a(c.src);if(f.length){var g=f[0].parentNode;g&&g.tagName&&(r||(q=e.hiddenClass,r=l(q),q="mfp-"+q),s=f.after(r).detach().removeClass(q)),b.updateStatus("ready")}else b.updateStatus("error",e.tNotFound),f=a("<div>");return c.inlineElement=f,f}return b.updateStatus("ready"),b._parseMarkup(d,{},c),d}}});var u,v=function(){u&&a(document.body).removeClass(u)},w=function(){v(),b.req&&b.req.abort()};a.magnificPopup.registerModule("ajax",{options:{settings:null,cursor:"mfp-ajax-cur",tError:'<a href="%url%">The content</a> could not be loaded.'},proto:{initAjax:function(){b.types.push("ajax"),u=b.st.ajax.cursor,k("Close.ajax",w),k("BeforeChange.ajax",w)},getAjax:function(c){u&&a(document.body).addClass(u),b.updateStatus("loading");var d=a.extend({url:c.src,success:function(d,e,f){var g={data:d,xhr:f};m("ParseAjax",g),b.appendContent(a(g.data),"ajax"),c.finished=!0,v(),b._setFocus(),setTimeout(function(){b.wrap.addClass("mfp-ready")},16),b.updateStatus("ready"),m("AjaxContentAdded")},error:function(){v(),c.finished=c.loadError=!0,b.updateStatus("error",b.st.ajax.tError.replace("%url%",c.src))}},b.st.ajax.settings);return b.req=a.ajax(d),""}}});var x,y=function(c){if(c.data&&void 0!==c.data.title)return c.data.title;var d=b.st.image.titleSrc;if(d){if(a.isFunction(d))return d.call(b,c);if(c.el)return c.el.attr(d)||""}return""};a.magnificPopup.registerModule("image",{options:{markup:'<div class="mfp-figure"><div class="mfp-close"></div><figure><div class="mfp-img"></div><figcaption><div class="mfp-bottom-bar"><div class="mfp-title"></div><div class="mfp-counter"></div></div></figcaption></figure></div>',cursor:"mfp-zoom-out-cur",titleSrc:"title",verticalFit:!0,tError:'<a href="%url%">The image</a> could not be loaded.'},proto:{initImage:function(){var c=b.st.image,d=".image";b.types.push("image"),k("Open"+d,function(){"image"===b.currItem.type&&c.cursor&&a(document.body).addClass(c.cursor)}),k("Close"+d,function(){c.cursor&&a(document.body).removeClass(c.cursor),j.off("resize.mfp")}),k("Resize"+d,b.resizeImage),b.isLowIE&&k("AfterChange",b.resizeImage)},resizeImage:function(){var a=b.currItem;if(a&&a.img&&b.st.image.verticalFit){var c=0;b.isLowIE&&(c=parseInt(a.img.css("padding-top"),10)+parseInt(a.img.css("padding-bottom"),10)),a.img.css("max-height",b.wH-c)}},_onImageHasSize:function(a){a.img&&(a.hasSize=!0,x&&clearInterval(x),a.isCheckingImgSize=!1,m("ImageHasSize",a),a.imgHidden&&(b.content&&b.content.removeClass("mfp-loading"),a.imgHidden=!1))},findImageSize:function(a){var c=0,d=a.img[0],e=function(f){x&&clearInterval(x),x=setInterval(function(){if(d.naturalWidth>0)return void b._onImageHasSize(a);c>200&&clearInterval(x),c++,3===c?e(10):40===c?e(50):100===c&&e(500)},f)};e(1)},getImage:function(c,d){var e=0,f=function(){c&&(c.img[0].complete?(c.img.off(".mfploader"),c===b.currItem&&(b._onImageHasSize(c),b.updateStatus("ready")),c.hasSize=!0,c.loaded=!0,m("ImageLoadComplete")):(e++,e<200?setTimeout(f,100):g()))},g=function(){c&&(c.img.off(".mfploader"),c===b.currItem&&(b._onImageHasSize(c),b.updateStatus("error",h.tError.replace("%url%",c.src))),c.hasSize=!0,c.loaded=!0,c.loadError=!0)},h=b.st.image,i=d.find(".mfp-img");if(i.length){var j=document.createElement("img");j.className="mfp-img",c.el&&c.el.find("img").length&&(j.alt=c.el.find("img").attr("alt")),c.img=a(j).on("load.mfploader",f).on("error.mfploader",g),j.src=c.src,i.is("img")&&(c.img=c.img.clone()),j=c.img[0],j.naturalWidth>0?c.hasSize=!0:j.width||(c.hasSize=!1)}return b._parseMarkup(d,{title:y(c),img_replaceWith:c.img},c),b.resizeImage(),c.hasSize?(x&&clearInterval(x),c.loadError?(d.addClass("mfp-loading"),b.updateStatus("error",h.tError.replace("%url%",c.src))):(d.removeClass("mfp-loading"),b.updateStatus("ready")),d):(b.updateStatus("loading"),c.loading=!0,c.hasSize||(c.imgHidden=!0,d.addClass("mfp-loading"),b.findImageSize(c)),d)}}});var z,A=function(){return void 0===z&&(z=void 0!==document.createElement("p").style.MozTransform),z};a.magnificPopup.registerModule("zoom",{options:{enabled:!1,easing:"ease-in-out",duration:300,opener:function(a){return a.is("img")?a:a.find("img")}},proto:{initZoom:function(){var a,c=b.st.zoom,d=".zoom";if(c.enabled&&b.supportsTransition){var e,f,g=c.duration,h=function(a){var b=a.clone().removeAttr("style").removeAttr("class").addClass("mfp-animated-image"),d="all "+c.duration/1e3+"s "+c.easing,e={position:"fixed",zIndex:9999,left:0,top:0,"-webkit-backface-visibility":"hidden"},f="transition";return e["-webkit-"+f]=e["-moz-"+f]=e["-o-"+f]=e[f]=d,b.css(e),b},i=function(){b.content.css("visibility","visible")};k("BuildControls"+d,function(){if(b._allowZoom()){if(clearTimeout(e),b.content.css("visibility","hidden"),!(a=b._getItemToZoom()))return void i();f=h(a),f.css(b._getOffset()),b.wrap.append(f),e=setTimeout(function(){f.css(b._getOffset(!0)),e=setTimeout(function(){i(),setTimeout(function(){f.remove(),a=f=null,m("ZoomAnimationEnded")},16)},g)},16)}}),k("BeforeClose"+d,function(){if(b._allowZoom()){if(clearTimeout(e),b.st.removalDelay=g,!a){if(!(a=b._getItemToZoom()))return;f=h(a)}f.css(b._getOffset(!0)),b.wrap.append(f),b.content.css("visibility","hidden"),setTimeout(function(){f.css(b._getOffset())},16)}}),k("Close"+d,function(){b._allowZoom()&&(i(),f&&f.remove(),a=null)})}},_allowZoom:function(){return"image"===b.currItem.type},_getItemToZoom:function(){return!!b.currItem.hasSize&&b.currItem.img},_getOffset:function(c){var d;d=c?b.currItem.img:b.st.zoom.opener(b.currItem.el||b.currItem);var e=d.offset(),f=parseInt(d.css("padding-top"),10),g=parseInt(d.css("padding-bottom"),10);e.top-=a(window).scrollTop()-f;var h={width:d.width(),height:(i?d.innerHeight():d[0].offsetHeight)-g-f};return A()?h["-moz-transform"]=h.transform="translate("+e.left+"px,"+e.top+"px)":(h.left=e.left,h.top=e.top),h}}});var B=function(a){if(b.currTemplate.iframe){var c=b.currTemplate.iframe.find("iframe");c.length&&(a||(c[0].src="//about:blank"),b.isIE8&&c.css("display",a?"block":"none"))}};a.magnificPopup.registerModule("iframe",{options:{markup:'<div class="mfp-iframe-scaler"><div class="mfp-close"></div><iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe></div>',srcAction:"iframe_src",patterns:{youtube:{index:"youtube.com",id:"v=",src:"//www.youtube.com/embed/%id%?autoplay=1"},vimeo:{index:"vimeo.com/",id:"/",src:"//player.vimeo.com/video/%id%?autoplay=1"},gmaps:{index:"//maps.google.",src:"%id%&output=embed"}}},proto:{initIframe:function(){b.types.push("iframe"),k("BeforeChange",function(a,b,c){b!==c&&("iframe"===b?B():"iframe"===c&&B(!0))}),k("Close.iframe",function(){B()})},getIframe:function(c,d){var e=c.src,f=b.st.iframe;a.each(f.patterns,function(){if(e.indexOf(this.index)>-1)return this.id&&(e="string"==typeof this.id?e.substr(e.lastIndexOf(this.id)+this.id.length,e.length):this.id.call(this,e)),e=this.src.replace("%id%",e),!1});var g={};return f.srcAction&&(g[f.srcAction]=e),b._parseMarkup(d,g,c),b.updateStatus("ready"),d}}});var C=function(a){var c=b.items.length;return a>c-1?a-c:a<0?c+a:a},D=function(a,b,c){return a.replace(/%curr%/gi,b+1).replace(/%total%/gi,c)};a.magnificPopup.registerModule("gallery",{options:{enabled:!1,arrowMarkup:'<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',preload:[0,2],navigateByImgClick:!0,arrows:!0,tPrev:"Previous (Left arrow key)",tNext:"Next (Right arrow key)",tCounter:"%curr% of %total%"},proto:{initGallery:function(){var c=b.st.gallery,e=".mfp-gallery",g=Boolean(a.fn.mfpFastClick);if(b.direction=!0,!c||!c.enabled)return!1;f+=" mfp-gallery",k("Open"+e,function(){c.navigateByImgClick&&b.wrap.on("click"+e,".mfp-img",function(){if(b.items.length>1)return b.next(),!1}),d.on("keydown"+e,function(a){37===a.keyCode?b.prev():39===a.keyCode&&b.next()})}),k("UpdateStatus"+e,function(a,c){c.text&&(c.text=D(c.text,b.currItem.index,b.items.length))}),k("MarkupParse"+e,function(a,d,e,f){var g=b.items.length;e.counter=g>1?D(c.tCounter,f.index,g):""}),k("BuildControls"+e,function(){if(b.items.length>1&&c.arrows&&!b.arrowLeft){var d=c.arrowMarkup,e=b.arrowLeft=a(d.replace(/%title%/gi,c.tPrev).replace(/%dir%/gi,"left")).addClass("mfp-prevent-close"),f=b.arrowRight=a(d.replace(/%title%/gi,c.tNext).replace(/%dir%/gi,"right")).addClass("mfp-prevent-close"),h=g?"mfpFastClick":"click";e[h](function(){b.prev()}),f[h](function(){b.next()}),b.isIE7&&(l("b",e[0],!1,!0),l("a",e[0],!1,!0),l("b",f[0],!1,!0),l("a",f[0],!1,!0)),b.container.append(e.add(f))}}),k("Change"+e,function(){b._preloadTimeout&&clearTimeout(b._preloadTimeout),b._preloadTimeout=setTimeout(function(){b.preloadNearbyImages(),b._preloadTimeout=null},16)}),k("Close"+e,function(){d.off(e),b.wrap.off("click"+e),b.arrowLeft&&g&&b.arrowLeft.add(b.arrowRight).destroyMfpFastClick(),b.arrowRight=b.arrowLeft=null})},next:function(){b.direction=!0,b.index=C(b.index+1),b.updateItemHTML()},prev:function(){b.direction=!1,b.index=C(b.index-1),b.updateItemHTML()},goTo:function(a){b.direction=a>=b.index,b.index=a,b.updateItemHTML()},preloadNearbyImages:function(){var a,c=b.st.gallery.preload,d=Math.min(c[0],b.items.length),e=Math.min(c[1],b.items.length);for(a=1;a<=(b.direction?e:d);a++)b._preloadItem(b.index+a);for(a=1;a<=(b.direction?d:e);a++)b._preloadItem(b.index-a)},_preloadItem:function(c){if(c=C(c),!b.items[c].preloaded){var d=b.items[c];d.parsed||(d=b.parseEl(c)),m("LazyLoad",d),"image"===d.type&&(d.img=a('<img class="mfp-img" />').on("load.mfploader",function(){d.hasSize=!0}).on("error.mfploader",function(){d.hasSize=!0,d.loadError=!0,m("LazyLoadError",d)}).attr("src",d.src)),d.preloaded=!0}}}});a.magnificPopup.registerModule("retina",{options:{replaceSrc:function(a){return a.src.replace(/\.\w+$/,function(a){return"@2x"+a})},ratio:1},proto:{initRetina:function(){if(window.devicePixelRatio>1){var a=b.st.retina,c=a.ratio;c=isNaN(c)?c():c,c>1&&(k("ImageHasSize.retina",function(a,b){b.img.css({"max-width":b.img[0].naturalWidth/c,width:"100%"})}),k("ElementParse.retina",function(b,d){d.src=a.replaceSrc(d,c)}))}}}}),function(){var b="ontouchstart"in window,c=function(){j.off("touchmove"+d+" touchend"+d)},d=".mfpFastClick";a.fn.mfpFastClick=function(e){return a(this).each(function(){var f,g=a(this);if(b){var h,i,k,l,m,n;g.on("touchstart"+d,function(a){l=!1,n=1,m=a.originalEvent?a.originalEvent.touches[0]:a.touches[0],i=m.clientX,k=m.clientY,j.on("touchmove"+d,function(a){m=a.originalEvent?a.originalEvent.touches:a.touches,n=m.length,m=m[0],(Math.abs(m.clientX-i)>10||Math.abs(m.clientY-k)>10)&&(l=!0,c())}).on("touchend"+d,function(a){c(),l||n>1||(f=!0,a.preventDefault(),clearTimeout(h),h=setTimeout(function(){f=!1},1e3),e())})})}g.on("click"+d,function(){f||e()})})},a.fn.destroyMfpFastClick=function(){a(this).off("touchstart"+d+" click"+d),b&&j.off("touchmove"+d+" touchend"+d)}}(),o()}),"function"!=typeof Object.create&&(Object.create=function(a){function b(){}return b.prototype=a,new b}),function(a,b,c,d){var e={init:function(b,c){var d=this;d.elem=c,d.$elem=a(c),d.options=a.extend({},a.fn.rtTab.options,b),d.rtTabs()},rtTabs:function(){var c=this,d=c.options.activeTab;if(c.$elem.find("li:nth-child("+d+")").addClass("active"),c.rtTabContent(activeTabContent="yes"),c.rtClick(),!0==("false"!==c.$elem.attr("data-hash"))){var e=b.location.hash;e&&c.$elem.find("li").find('a[href="'+e+'"]').trigger("click"),a(b).on("hashchange",function(){var a=b.location.hash;c.$elem.find("li").find('a[href="'+a+'"]').trigger("click")})}},rtClick:function(){var c=this,d=c.$elem.find("li");d.find("a").on("click",function(e){e.preventDefault(),d.removeClass("active"),c.rtTabContent(),a(this).parent().addClass("active");var f=a(this).attr("href");if(a(f).removeClass("hide"),1==("false"!==c.$elem.attr("data-hash"))){var g=a(b).scrollTop();location.hash=a(this).attr("href"),a(b).scrollTop(g)}"function"==typeof c.options.onComplete&&c.options.onComplete.apply(c.elem,arguments)})},rtTabContent:function(b){this.$elem.find("li").find("a").each(function(){var c=a(this),d=c.attr("href");"yes"===b?c.parent().hasClass("active")||a(d).addClass("hide"):a(d).addClass("hide")})}};a.fn.rtTab=function(b){return this.each(function(){var c=Object.create(e);c.init(b,this),a.data(this,"rtTab",c)})},a.fn.rtTab.options={activeTab:1,onComplete:null}}(jQuery,window,document);var rtMagnificPopup,rtm_masonry_container,comment_media=!1,rtMediaHook={hooks:[],is_break:!1,register:function(a,b){void 0===rtMediaHook.hooks[a]&&(rtMediaHook.hooks[a]=[]),rtMediaHook.hooks[a].push(b)},call:function(a,arguments){if(void 0!==rtMediaHook.hooks[a])for(i=0;i<rtMediaHook.hooks[a].length;++i)if(1!=rtMediaHook.hooks[a][i](arguments))return rtMediaHook.is_break=!0,!1;return!0}};jQuery("document").ready(function(a){function b(){if(jQuery("#rtmedia-media-view-form").length>0){var a=jQuery("#rtmedia-media-view-form").attr("action");jQuery.post(a,{},function(a){})}}function c(){var a=jQuery.magnificPopup.instance,b=a.probablyMobile,c=e("rtmedia-touch-swipe-tooltip");b&&""===c?(jQuery("#mobile-swipe-overlay").show(),jQuery("#mobile-swipe-overlay").on("click",function(a){d("rtmedia-touch-swipe-tooltip",!0,365),jQuery(this).hide(),jQuery("#rtmedia-single-media-container .mejs-playpause-button").trigger("click")}),jQuery("#mobile-swipe-overlay").swipe({swipe:function(a,b,c,e,f,g){d("rtmedia-touch-swipe-tooltip",!0,365),jQuery("#mobile-swipe-overlay").hide(),
|
7 |
+
jQuery("#rtmedia-single-media-container .mejs-playpause-button").trigger("click")},threshold:0})):jQuery("#rtmedia-single-media-container .mejs-playpause-button").trigger("click"),jQuery(".mfp-arrow-right").on("click",function(b){a.next()}),jQuery(".mfp-arrow-left").on("click",function(b){a.prev()}),jQuery(".mfp-content .rtmedia-media").swipe({swipeLeft:function(b,c,d,e,f){a.next()},swipeRight:function(b,c,d,e,f){a.prev()},threshold:0})}function d(a,b,c){var d=new Date;d.setTime(d.getTime()+24*c*60*60*1e3);var e="expires="+d.toUTCString();document.cookie=a+"="+b+";"+e+";path=/"}function e(a){for(var b=a+"=",c=document.cookie.split(";"),d=0;d<c.length;d++){for(var e=c[d];" "==e.charAt(0);)e=e.substring(1);if(0==e.indexOf(b))return e.substring(b.length,e.length)}return""}function f(){jQuery(".mfp-arrow-right").hide(),jQuery(".mfp-arrow-left").hide(),jQuery(document).unbind("keydown")}function g(){rtmedia_disable_popup_navigation("#comment_content")}function h(){jQuery(".rtmedia-container").on("click",".rtmedia-delete-media",function(a){a.preventDefault(),confirm(rtmedia_media_delete_confirmation)&&jQuery(this).closest("form").submit()})}jQuery(document).ajaxComplete(function(a,b,c){if("legacy"!==bp_template_pack&&bp_template_pack){var d=get_parameter("action",c.data);"activity_filter"!==d&&"post_update"!==d&&"get_single_activity_content"!==d&&"activity_get_older_updates"!==d||"undefined"==typeof rtmedia_masonry_layout||"true"!==rtmedia_masonry_layout||"undefined"==typeof rtmedia_masonry_layout_activity||"true"!==rtmedia_masonry_layout_activity?"activity_filter"!==d&&"post_update"!==d&&"get_single_activity_content"!==d&&"activity_get_older_updates"!==d||setTimeout(function(){apply_rtMagnificPopup(".rtmedia-list-media.rtm-gallery-list, .rtmedia-activity-container ul.rtmedia-list, #bp-media-list,.bp-media-sc-list, li.media.album_updated ul,ul.bp-media-list-media, li.activity-item div.activity-content div.activity-inner div.bp_media_content, .rtm-bbp-container, ul.rtm-comment-container"),rtmedia_activity_stream_comment_media()},1e3):setTimeout(function(){apply_rtMagnificPopup(".rtmedia-list-media.rtm-gallery-list, .rtmedia-activity-container ul.rtmedia-list, #bp-media-list,.bp-media-sc-list, li.media.album_updated ul,ul.bp-media-list-media, li.activity-item div.activity-content div.activity-inner div.bp_media_content, .rtm-bbp-container, ul.rtm-comment-container"),rtmedia_activity_masonry(),rtmedia_activity_stream_comment_media()},1e3)}}),jQuery(".rtmedia-uploader-div").css({opacity:"1",display:"block",visibility:"visible"}),jQuery(" #whats-new-options ").css({opacity:"1"}),void 0!==a.fn.rtTab&&a(".rtm-tabs").rtTab(),jQuery(".rtmedia-modal-link").length>0&&a(".rtmedia-modal-link").magnificPopup({type:"inline",midClick:!0,closeBtnInside:!0}),a("#rt_media_comment_form").submit(function(b){return""!=a.trim(a("#comment_content").val())||(0==jQuery("#rtmedia-single-media-container").length?rtmedia_gallery_action_alert_message(rtmedia_empty_comment_msg,"warning"):rtmedia_single_media_alert_message(rtmedia_empty_comment_msg,"warning"),!1)}),a("li.rtmedia-list-item p a").each(function(b){a(this).addClass("no-popup")}),a("li.rtmedia-list-item p a").each(function(b){a(this).addClass("no-popup")}),"undefined"!=typeof rtmedia_lightbox_enabled&&"1"==rtmedia_lightbox_enabled&&apply_rtMagnificPopup(".rtmedia-list-media.rtm-gallery-list, .rtmedia-activity-container ul.rtmedia-list, #bp-media-list,.bp-media-sc-list, li.media.album_updated ul,ul.bp-media-list-media, li.activity-item div.activity-content div.activity-inner div.bp_media_content, .rtm-bbp-container, ul.rtm-comment-container"),jQuery.ajaxPrefilter(function(a,b,c){try{if(null==b.data||void 0===b.data||void 0===b.data.action)return!0}catch(a){return!0}if("activity_get_older_updates"==b.data.action){var d=b.success;a.success=function(a){"function"==typeof d&&d(a),apply_rtMagnificPopup(".rtmedia-activity-container ul.rtmedia-list, #bp-media-list, .bp-media-sc-list, li.media.album_updated ul,ul.bp-media-list-media, li.activity-item div.activity-content div.activity-inner div.bp_media_content"),rtMediaHook.call("rtmedia_js_after_activity_added",[])}}else if("get_single_activity_content"==b.data.action){var d=b.success;a.success=function(a){"function"==typeof d&&d(a),setTimeout(function(){apply_rtMagnificPopup(".rtmedia-activity-container ul.rtmedia-list, #bp-media-list, .bp-media-sc-list, li.media.album_updated ul,ul.bp-media-list-media, li.activity-item div.activity-content div.activity-inner div.bp_media_content"),jQuery("ul.activity-list li.rtmedia_update:first-child .wp-audio-shortcode, ul.activity-list li.rtmedia_update:first-child .wp-video-shortcode").mediaelementplayer({classPrefix:"mejs-",defaultVideoWidth:480,defaultVideoHeight:270})},900)}}}),jQuery.ajaxPrefilter(function(a,b,c){try{if(null==b.data||void 0===b.data||void 0===b.data.action)return!0}catch(a){return!0}if("activity_get_older_updates"==b.data.action){var d=b.success;a.success=function(a){"function"==typeof d&&d(a),apply_rtMagnificPopup(".rtmedia-activity-container ul.rtmedia-list, #bp-media-list, .bp-media-sc-list, li.media.album_updated ul,ul.bp-media-list-media, li.activity-item div.activity-content div.activity-inner div.bp_media_content"),jQuery("ul.activity-list li.rtmedia_update div.rtmedia-item-thumbnail > audio.wp-audio-shortcode, ul.activity-list li.rtmedia_update div.rtmedia-item-thumbnail > video.wp-video-shortcode").mediaelementplayer({classPrefix:"mejs-",defaultVideoWidth:480,defaultVideoHeight:270}),setTimeout(function(){rtmedia_activity_stream_comment_media()},900),rtMediaHook.call("rtmedia_js_after_activity_added",[])}}}),jQuery(".rtmedia-container").on("click",".select-all",function(a){jQuery(this).toggleClass("unselect-all").toggleClass("select-all"),jQuery(this).attr("title",rtmedia_unselect_all_visible),jQuery(".rtmedia-list input").each(function(){jQuery(this).prop("checked",!0)}),jQuery(".rtmedia-list-item").addClass("bulk-selected")}),jQuery(".rtmedia-container").on("click",".unselect-all",function(a){jQuery(this).toggleClass("select-all").toggleClass("unselect-all"),jQuery(this).attr("title",rtmedia_select_all_visible),jQuery(".rtmedia-list input").each(function(){jQuery(this).prop("checked",!1)}),jQuery(".rtmedia-list-item").removeClass("bulk-selected")}),jQuery(".rtmedia-container").on("click",".rtmedia-move",function(a){jQuery(".rtmedia-delete-container").slideUp(),jQuery(".rtmedia-move-container").slideToggle()}),jQuery("#rtmedia-create-album-modal").on("click","#rtmedia_create_new_album",function(b){if($albumname=jQuery("<span/>").text(jQuery.trim(jQuery("#rtmedia_album_name").val())).html(),$album_description=jQuery("#rtmedia_album_description"),$context=jQuery.trim(jQuery("#rtmedia_album_context").val()),$context_id=jQuery.trim(jQuery("#rtmedia_album_context_id").val()),$privacy=jQuery.trim(jQuery("#rtmedia_select_album_privacy").val()),$create_album_nonce=jQuery.trim(jQuery("#rtmedia_create_album_nonce").val()),""!=$albumname){var c={action:"rtmedia_create_album",name:$albumname,description:$album_description.val(),context:$context,context_id:$context_id,create_album_nonce:$create_album_nonce};""!==$privacy&&(c.privacy=$privacy),a("#rtmedia_create_new_album").attr("disabled","disabled");var d=a("#rtmedia_create_new_album").html();a("#rtmedia_create_new_album").prepend("<img src='"+rMedia_loading_file+"' />"),jQuery.post(rtmedia_ajax_url,c,function(b){if(void 0!==b.album){b=jQuery.trim(b.album);var c=!0;$album_description.val(""),a("#rtmedia_album_name").focus(),jQuery(".rtmedia-user-album-list").each(function(){if(jQuery(this).children("optgroup").each(function(){if(jQuery(this).attr("value")===$context)return c=!1,void jQuery(this).append('<option value="'+b+'">'+$albumname+"</option>")}),c){var a=$context.charAt(0).toUpperCase()+$context.slice(1)+" "+rtmedia_main_js_strings.rtmedia_albums,d='<optgroup value="'+$context+'" label="'+a+'"><option value="'+b+'">'+$albumname+"</option></optgroup>";jQuery(this).append(d)}}),jQuery('select.rtmedia-user-album-list option[value="'+b+'"]').prop("selected",!0),jQuery(".rtmedia-create-new-album-container").slideToggle(),jQuery("#rtmedia_album_name").val(""),jQuery("#rtmedia-create-album-modal").append("<div class='rtmedia-success rtmedia-create-album-alert'><b>"+$albumname+"</b>"+rtmedia_album_created_msg+"</div>"),setTimeout(function(){jQuery(".rtmedia-create-album-alert").remove()},4e3),setTimeout(function(){galleryObj.reloadView(),jQuery(".close-reveal-modal").click()},2e3)}else void 0!==b.error?rtmedia_gallery_action_alert_message(b.error,"warning"):rtmedia_gallery_action_alert_message(rtmedia_something_wrong_msg,"warning");a("#rtmedia_create_new_album").removeAttr("disabled"),a("#rtmedia_create_new_album").html(d)})}else rtmedia_gallery_action_alert_message(rtmedia_empty_album_name_msg,"warning")}),jQuery(".rtmedia-container").on("click",".rtmedia-delete-selected",function(a){jQuery(".rtmedia-list :checkbox:checked").length>0?confirm(rtmedia_selected_media_delete_confirmation)&&jQuery(this).closest("form").attr("action","../../../"+rtmedia_media_slug+"/delete").submit():rtmedia_gallery_action_alert_message(rtmedia_no_media_selected,"warning")}),jQuery(".rtmedia-container").on("click",".rtmedia-move-selected",function(a){jQuery(".rtmedia-list :checkbox:checked").length>0?confirm(rtmedia_selected_media_move_confirmation)&&jQuery(this).closest("form").attr("action","").submit():rtmedia_gallery_action_alert_message(rtmedia_no_media_selected,"warning")}),jQuery("#buddypress").on("change",".rtm-activity-privacy-opt",function(){var a=jQuery(this).attr("id");a=a.split("-"),a=a[a.length-1];var b=this;data={activity_id:a,privacy:jQuery(this).val(),nonce:jQuery("#rtmedia_activity_privacy_nonce").val(),action:"rtm_change_activity_privacy"},jQuery.post(ajaxurl,data,function(a){var c="",d="";"true"==a?(c=rtmedia_main_js_strings.privacy_update_success,d="success"):(c=rtmedia_main_js_strings.privacy_update_error,d="fail"),jQuery(b).after('<p class="rtm-ac-privacy-updated '+d+'">'+c+"</p>"),setTimeout(function(){jQuery(b).siblings(".rtm-ac-privacy-updated").remove()},2e3)})}),jQuery(".media_search_input").on("keyup",function(){rtm_search_media_text_validation()}),b(),rtMediaHook.register("rtmedia_js_popup_after_content_added",function(){b(),h(),mfp=jQuery.magnificPopup.instance,jQuery(mfp.items).size()>1&&0==comment_media?c():f(),g(),rtmedia_disable_popup_navigation_comment_media_focus();var d=a(window).height();jQuery(".rtm-lightbox-container .mejs-video").css({height:.8*d,"over-flow":"hidden"}),jQuery(".mfp-content .rtmedia-media").css({"max-height":.87*d,"over-flow":"hidden"}),rtmedia_init_action_dropdown(".rtm-lightbox-container .rtmedia-actions"),jQuery(".rtmedia-comment-link").on("click",function(a){a.preventDefault(),jQuery("#comment_content").focus()}),jQuery(".rtm-more").shorten({showChars:130});var e=a(".rtm-gallery-title"),i="";""!=(i=a.isEmptyObject(e)?a("#subnav.item-list-tabs li.selected ").html():e.html())&&a(".rtm-ltb-gallery-title .ltb-title").html(i);var j=a("#subnav.item-list-tabs li.selected span").html();return a("li.total").html(j),!0});var i=jQuery("#drag-drop-area"),j=jQuery("#whats-new");i.html();jQuery("#rtmedia-upload-container").after("<div id='rtm-drop-files-title'>"+rtmedia_drop_media_msg+"</div>"),"undefined"!=typeof rtmedia_bp_enable_activity&&"1"==rtmedia_bp_enable_activity&&jQuery("#whats-new-textarea").append("<div id='rtm-drop-files-title'>"+rtmedia_drop_media_msg+"</div>"),jQuery(document).on("dragover",function(a){a.preventDefault(),a.target!=this&&(jQuery("#rtm-media-gallery-uploader").show(),"undefined"!=typeof rtmedia_bp_enable_activity&&"1"==rtmedia_bp_enable_activity&&j.addClass("rtm-drag-drop-active"),i.addClass("rtm-drag-drop-active"),jQuery("#rtm-drop-files-title").show())}).on("dragleave",function(a){if(a.preventDefault(),0!=a.originalEvent.pageX&&0!=a.originalEvent.pageY)return!1;"undefined"!=typeof rtmedia_bp_enable_activity&&"1"==rtmedia_bp_enable_activity&&(j.removeClass("rtm-drag-drop-active"),j.removeAttr("style")),i.removeClass("rtm-drag-drop-active"),jQuery("#rtm-drop-files-title").hide()}).on("drop",function(a){a.preventDefault(),jQuery(".bp-suggestions").focus(),"undefined"!=typeof rtmedia_bp_enable_activity&&"1"==rtmedia_bp_enable_activity&&(j.removeClass("rtm-drag-drop-active"),j.removeAttr("style")),i.removeClass("rtm-drag-drop-active"),jQuery("#rtm-drop-files-title").hide()}),jQuery(".rtmedia-container").on("click",".rtmedia-delete-album",function(a){a.preventDefault(),confirm(rtmedia_album_delete_confirmation)&&jQuery(this).closest("form").submit()}),jQuery(".rtmedia-container").on("click",".rtmedia-delete-media",function(a){a.preventDefault(),confirm(rtmedia_media_delete_confirmation)&&jQuery(this).closest("form").submit()}),rtmedia_init_action_dropdown(""),a(document).click(function(){a(".click-nav ul").is(":visible")&&a(".click-nav ul",this).hide()}),jQuery(".rtmedia-comment-link").on("click",function(a){a.preventDefault(),jQuery("#comment_content").focus()}),jQuery(".rtm-more").length>0&&a(".rtm-more").shorten({showChars:200}),"undefined"!=typeof rtmedia_masonry_layout&&"true"==rtmedia_masonry_layout&&"undefined"!=typeof rtmedia_masonry_layout_activity&&"true"==rtmedia_masonry_layout_activity&&rtmedia_activity_masonry(),jQuery(document).ajaxComplete(function(a,b,c){var d=get_parameter("action",c.data);"post_update"!==d&&"get_single_activity_content"!==d&&"activity_get_older_updates"!==d||"undefined"==typeof rtmedia_masonry_layout||"true"!=rtmedia_masonry_layout||"undefined"==typeof rtmedia_masonry_layout_activity||"true"!=rtmedia_masonry_layout_activity||rtmedia_activity_masonry()}),"undefined"!=typeof rtmedia_masonry_layout&&"true"==rtmedia_masonry_layout&&0==jQuery(".rtmedia-container .rtmedia-list.rtm-no-masonry").length&&(rtm_masonry_container=jQuery(".rtmedia-container .rtmedia-list"),rtm_masonry_container.masonry({itemSelector:".rtmedia-list-item"}),setInterval(function(){jQuery.each(jQuery(".rtmedia-list.masonry .rtmedia-item-title"),function(a,b){jQuery(b).width(jQuery(b).siblings(".rtmedia-item-thumbnail").children("img").width())}),rtm_masonry_reload(rtm_masonry_container)},1e3),jQuery.each(jQuery(".rtmedia-list.masonry .rtmedia-item-title"),function(a,b){jQuery(b).width(jQuery(b).siblings(".rtmedia-item-thumbnail").children("img").width())})),jQuery(".rtm-uploader-tabs").length>0&&jQuery(".rtm-uploader-tabs li").click(function(a){jQuery(this).hasClass("active")||(jQuery(this).siblings().removeClass("active"),jQuery(this).parents(".rtm-uploader-tabs").siblings().hide(),class_name=jQuery(this).attr("class"),jQuery(this).parents(".rtm-uploader-tabs").siblings('[data-id="'+class_name+'"]').show(),jQuery(this).addClass("active"),"rtm-upload-tab"!=class_name?jQuery("div.moxie-shim").hide():jQuery("div.moxie-shim").show())}),jQuery(".rtmedia-container").on("click",".rtm-delete-media",function(a){a.preventDefault();var b="Are you sure you want to delete this media?";if("undefined"!=typeof rtmedia_media_delete_confirmation&&(b=rtmedia_media_delete_confirmation),confirm(b)){var c=jQuery(this).closest("li"),d=jQuery("#rtmedia_media_delete_nonce").val(),e={action:"delete_uploaded_media",nonce:d,media_id:c.attr("id")};jQuery.ajax({url:ajaxurl,type:"post",data:e,success:function(a){"1"==a?(rtmedia_gallery_action_alert_message(rtmedia_main_js_strings.file_delete_success,"success"),c.remove(),"undefined"!=typeof rtmedia_masonry_layout&&"true"==rtmedia_masonry_layout&&0==jQuery(".rtmedia-container .rtmedia-list.rtm-no-masonry").length&&rtm_masonry_reload(rtm_masonry_container)):rtmedia_gallery_action_alert_message(rtmedia_file_not_deleted,"warning")}})}})}),function(a){a.fn.shorten=function(b){"use strict";var c={showChars:100,minHideChars:10,ellipsesText:"...",moreText:rtmedia_read_more,lessText:rtmedia__show_less,onLess:function(){},onMore:function(){},errMsg:null,force:!1};return b&&a.extend(c,b),!(a(this).data("jquery.shorten")&&!c.force)&&(a(this).data("jquery.shorten",!0),a(document).off("click",".morelink"),a(document).on({click:function(){var b=a(this);return b.hasClass("less")?(b.removeClass("less"),b.html(c.moreText),b.parent().prev().hide(0,function(){b.parent().prev().prev().show()}).hide(0,function(){c.onLess()})):(b.addClass("less"),b.html(c.lessText),b.parent().prev().show(0,function(){b.parent().prev().prev().hide()}).show(0,function(){c.onMore()})),!1}},".morelink"),this.each(function(){var b=a(this),d=b.html();if(b.text().length>c.showChars+c.minHideChars){var e=d.substr(0,c.showChars);if(e.indexOf("<")>=0){for(var f=!1,g="",h=0,i=[],k=null,l=0,m=0;m<=c.showChars;l++)if("<"!=d[l]||f||(f=!0,k=d.substring(l+1,d.indexOf(">",l)),"/"==k[0]?k!="/"+i[0]?c.errMsg="ERROR en HTML: the top of the stack should be the tag that closes":i.shift():"br"!=k.toLowerCase()&&i.unshift(k)),f&&">"==d[l]&&(f=!1),f)g+=d.charAt(l);else if(m++,h<=c.showChars)g+=d.charAt(l),h++;else if(i.length>0){for(j=0;j<i.length;j++)g+="</"+i[j]+">";break}e=a("<div/>").html(g+'<span class="ellip">'+c.ellipsesText+"</span>").html()}else e+=c.ellipsesText;var n='<div class="shortcontent">'+e+'</div><div class="allcontent">'+d+'</div><span><a href="javascript://nop/" class="morelink">'+c.moreText+"</a></span>";b.html(n),b.find(".allcontent").hide(),a(".shortcontent p:last",b).css("margin-bottom",0)}}))}}(jQuery),window.onload=function(){"undefined"!=typeof rtmedia_masonry_layout&&"true"==rtmedia_masonry_layout&&0==jQuery(".rtmedia-container .rtmedia-list.rtm-no-masonry").length&&rtm_masonry_reload(rtm_masonry_container),rtm_search_media_text_validation(),check_condition("search")&&jQuery("#media_search_remove").show()},jQuery(document).ready(function(){rtm_upload_terms_activity(),jQuery("body").hasClass("has-sidebar")&&0===jQuery("#secondary").length&&(jQuery(".rtmedia-single-container").length||jQuery(".rtmedia-container").length)&&jQuery("body").removeClass("has-sidebar")});
|
app/helper/RTMediaSupport.php
CHANGED
@@ -487,7 +487,7 @@ if ( ! class_exists( 'RTMediaSupport' ) ) {
|
|
487 |
for="name"><?php esc_html_e( 'Name', 'buddypress-media' ); ?></label>
|
488 |
<input class="bp-media-input" id="name" type="text" name="name" value="" required/>
|
489 |
<span class="rtm-tooltip">
|
490 |
-
<i class="dashicons dashicons-info
|
491 |
<span class="rtm-tip">
|
492 |
<?php esc_html_e( 'Use actual user name which used during purchased.', 'buddypress-media' ); ?>
|
493 |
</span>
|
@@ -499,7 +499,7 @@ if ( ! class_exists( 'RTMediaSupport' ) ) {
|
|
499 |
for="email"><?php esc_html_e( 'Email', 'buddypress-media' ); ?></label>
|
500 |
<input id="email" class="bp-media-input" type="text" name="email" value="" required/>
|
501 |
<span class="rtm-tooltip">
|
502 |
-
<i class="dashicons dashicons-info
|
503 |
<span class="rtm-tip">
|
504 |
<?php esc_html_e( 'Use email id which used during purchased', 'buddypress-media' ); ?>
|
505 |
</span>
|
@@ -543,7 +543,7 @@ if ( ! class_exists( 'RTMediaSupport' ) ) {
|
|
543 |
for="subject"><?php esc_html_e( 'Attachement', 'buddypress-media' ); ?></label>
|
544 |
<input id="debuglog" class="bp-media-input" type="file" name="debuglog" />
|
545 |
<span class="rtm-tooltip">
|
546 |
-
<i class="dashicons dashicons-info
|
547 |
<span class="rtm-tip">
|
548 |
<?php esc_html_e( 'Allowed file types are : images, documents and texts.', 'buddypress-media' ); ?>
|
549 |
</span>
|
487 |
for="name"><?php esc_html_e( 'Name', 'buddypress-media' ); ?></label>
|
488 |
<input class="bp-media-input" id="name" type="text" name="name" value="" required/>
|
489 |
<span class="rtm-tooltip">
|
490 |
+
<i class="dashicons dashicons-info"></i>
|
491 |
<span class="rtm-tip">
|
492 |
<?php esc_html_e( 'Use actual user name which used during purchased.', 'buddypress-media' ); ?>
|
493 |
</span>
|
499 |
for="email"><?php esc_html_e( 'Email', 'buddypress-media' ); ?></label>
|
500 |
<input id="email" class="bp-media-input" type="text" name="email" value="" required/>
|
501 |
<span class="rtm-tooltip">
|
502 |
+
<i class="dashicons dashicons-info"></i>
|
503 |
<span class="rtm-tip">
|
504 |
<?php esc_html_e( 'Use email id which used during purchased', 'buddypress-media' ); ?>
|
505 |
</span>
|
543 |
for="subject"><?php esc_html_e( 'Attachement', 'buddypress-media' ); ?></label>
|
544 |
<input id="debuglog" class="bp-media-input" type="file" name="debuglog" />
|
545 |
<span class="rtm-tooltip">
|
546 |
+
<i class="dashicons dashicons-info"></i>
|
547 |
<span class="rtm-tip">
|
548 |
<?php esc_html_e( 'Allowed file types are : images, documents and texts.', 'buddypress-media' ); ?>
|
549 |
</span>
|
app/main/controllers/activity/RTMediaActivity.php
CHANGED
@@ -34,16 +34,31 @@ class RTMediaActivity {
|
|
34 |
$this->privacy = $privacy;
|
35 |
}
|
36 |
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
}
|
48 |
|
49 |
global $rtmedia;
|
@@ -53,57 +68,122 @@ class RTMediaActivity {
|
|
53 |
$limit_activity_feed = 0;
|
54 |
}
|
55 |
|
56 |
-
$
|
57 |
-
$media_details = $
|
58 |
|
59 |
if ( intval( $limit_activity_feed ) > 0 ) {
|
60 |
$media_details = array_slice( $media_details, 0, $limit_activity_feed, true );
|
61 |
}
|
62 |
-
$rtmedia_activity_ul_class = apply_filters( 'rtmedia_'
|
63 |
-
$li_content = '';
|
64 |
-
$count = 0;
|
65 |
-
foreach ( $media_details as $media ) {
|
66 |
-
$li_content .= '<li class="rtmedia-list-item media-type-' . esc_attr( $media->media_type ) . '">';
|
67 |
-
if ( 'photo' === $media->media_type || 'document' === $media->media_type || 'other' === $media->media_type ) {
|
68 |
-
$li_content .= '<a href ="' . esc_url( get_rtmedia_permalink( $media->id ) ) . '">';
|
69 |
-
}
|
70 |
-
$li_content .= '<div class="rtmedia-item-thumbnail">';
|
71 |
-
|
72 |
-
$li_content .= $this->media( $media );
|
73 |
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
$
|
78 |
-
if ( 'photo' !== $media->media_type && 'document' !== $media->media_type && 'other' !== $media->media_type ) {
|
79 |
-
$li_content .= '<a href="' . esc_url( get_rtmedia_permalink( $media->id ) ) . '">';
|
80 |
-
}
|
81 |
|
82 |
-
|
83 |
-
|
84 |
-
$
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
}
|
91 |
|
92 |
-
$
|
93 |
$count ++;
|
94 |
}
|
95 |
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
$html .= '<ul class="rtmedia-'.$type.'-list ' . esc_attr( $rtmedia_activity_ul_class ) . ' rtmedia-activity-media-length-' . esc_attr( $count ) . '">';
|
100 |
}
|
101 |
|
102 |
-
$
|
103 |
-
|
104 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
|
106 |
-
return bp_activity_filter_kses( $
|
107 |
}
|
108 |
|
109 |
/**
|
34 |
$this->privacy = $privacy;
|
35 |
}
|
36 |
|
37 |
+
/**
|
38 |
+
* Function is used to generate HTML of activity/comments.
|
39 |
+
* It combines the rtMedia text and media in the activity content.
|
40 |
+
*
|
41 |
+
* Note: Use the `rtmedia_activity_content_html` filter to modify the output of the activity content.
|
42 |
+
*
|
43 |
+
* @param string $type Type of activity (activity/comment).
|
44 |
+
*
|
45 |
+
* @return string
|
46 |
+
*/
|
47 |
+
public function create_activity_html( $type = 'activity' ) {
|
48 |
+
$activity_container_start = sprintf( '<div class="rtmedia-%s-container">', esc_attr( $type ) );
|
49 |
+
$activity_container_end = '</div>';
|
50 |
+
|
51 |
+
$activity_text = '';
|
52 |
+
|
53 |
+
// Activity text content markup.
|
54 |
+
if ( ! empty( $this->activity_text ) && ' ' !== $this->activity_text ) {
|
55 |
+
$activity_text .= sprintf(
|
56 |
+
'<div class="rtmedia-%s-text">
|
57 |
+
<span>%s</span>
|
58 |
+
</div>',
|
59 |
+
esc_attr( $type ),
|
60 |
+
$this->activity_text
|
61 |
+
);
|
62 |
}
|
63 |
|
64 |
global $rtmedia;
|
68 |
$limit_activity_feed = 0;
|
69 |
}
|
70 |
|
71 |
+
$rtmedia_model = new RTMediaModel();
|
72 |
+
$media_details = $rtmedia_model->get( array( 'id' => $this->media ) );
|
73 |
|
74 |
if ( intval( $limit_activity_feed ) > 0 ) {
|
75 |
$media_details = array_slice( $media_details, 0, $limit_activity_feed, true );
|
76 |
}
|
77 |
+
$rtmedia_activity_ul_class = apply_filters( 'rtmedia_' . $type . '_ul_class', 'rtm-activity-media-list' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
|
79 |
+
$media_content = '';
|
80 |
+
$count = 0;
|
81 |
+
foreach ( $media_details as $media ) {
|
82 |
+
$media_content .= sprintf( '<li class="rtmedia-list-item media-type-%s">', esc_attr( $media->media_type ) );
|
|
|
|
|
|
|
83 |
|
84 |
+
if ( 'photo' === $media->media_type ) {
|
85 |
+
// Markup for photo media type with anchor tag only on image.
|
86 |
+
$media_content .= sprintf(
|
87 |
+
'<a href ="%s">
|
88 |
+
<div class="rtmedia-item-thumbnail">
|
89 |
+
%s
|
90 |
+
</div>
|
91 |
+
<div class="rtmedia-item-title">
|
92 |
+
<h4 title="%s">
|
93 |
+
%s
|
94 |
+
</h4>
|
95 |
+
</div>
|
96 |
+
</a>',
|
97 |
+
esc_url( get_rtmedia_permalink( $media->id ) ),
|
98 |
+
$this->media( $media ),
|
99 |
+
esc_attr( $media->media_title ),
|
100 |
+
$media->media_title
|
101 |
+
);
|
102 |
+
} elseif ( 'music' === $media->media_type || 'video' === $media->media_type ) {
|
103 |
+
// Markup for audio and video media type with link only on media (title).
|
104 |
+
$media_content .= sprintf(
|
105 |
+
'<div class="rtmedia-item-thumbnail">
|
106 |
+
%s
|
107 |
+
</div>
|
108 |
+
<div class="rtmedia-item-title">
|
109 |
+
<h4 title="%s">
|
110 |
+
<a href="%s">
|
111 |
+
%s
|
112 |
+
</a>
|
113 |
+
</h4>
|
114 |
+
</div>',
|
115 |
+
$this->media( $media ),
|
116 |
+
esc_attr( $media->media_title ),
|
117 |
+
esc_url( get_rtmedia_permalink( $media->id ) ),
|
118 |
+
esc_html( $media->media_title )
|
119 |
+
);
|
120 |
+
} else {
|
121 |
+
// Markup for all the other media linke docs and other files where anchor tag the markup is comming from add-on itself.
|
122 |
+
$media_content .= sprintf(
|
123 |
+
'<div class="rtmedia-item-thumbnail">
|
124 |
+
%s
|
125 |
+
</div>
|
126 |
+
<div class="rtmedia-item-title">
|
127 |
+
<h4 title="%s">
|
128 |
+
%s
|
129 |
+
</h4>
|
130 |
+
</div>',
|
131 |
+
$this->media( $media ),
|
132 |
+
esc_attr( $media->media_title ),
|
133 |
+
esc_html( $media->media_title )
|
134 |
+
);
|
135 |
}
|
136 |
|
137 |
+
$media_content .= '</li>';
|
138 |
$count ++;
|
139 |
}
|
140 |
|
141 |
+
$media_container_start_class = 'rtmedia-list';
|
142 |
+
if ( 'activity' !== $type ) {
|
143 |
+
$media_container_start_class = sprintf( 'rtmedia-%s-list', $type );
|
|
|
144 |
}
|
145 |
|
146 |
+
$media_container_start = sprintf(
|
147 |
+
'<ul class="%s %s rtmedia-activity-media-length-%s">',
|
148 |
+
esc_attr( $media_container_start_class ),
|
149 |
+
esc_attr( $rtmedia_activity_ul_class ),
|
150 |
+
esc_attr( $count )
|
151 |
+
);
|
152 |
+
|
153 |
+
$media_container_end = '</ul>';
|
154 |
+
|
155 |
+
$media_list = $media_container_start;
|
156 |
+
$media_list .= $media_content;
|
157 |
+
$media_list .= $media_container_end;
|
158 |
+
|
159 |
+
/**
|
160 |
+
* Filters the output of the activity contents before save.
|
161 |
+
*
|
162 |
+
* @param string $activity_content Concatination of $activity_text and $media_list.
|
163 |
+
* @param string $activity_text HTML markup of activity text.
|
164 |
+
* @param string $media_list HTML markup of media in ul.
|
165 |
+
*/
|
166 |
+
$activity_content = apply_filters( 'rtmedia_activity_content_html', $activity_text . $media_list, $activity_text, $media_list );
|
167 |
+
|
168 |
+
$activity = $activity_container_start;
|
169 |
+
$activity .= $activity_content;
|
170 |
+
$activity .= $activity_container_end;
|
171 |
+
|
172 |
+
// Bypass comment links limit.
|
173 |
+
add_filter(
|
174 |
+
'option_comment_max_links',
|
175 |
+
function ( $values ) {
|
176 |
+
$rtmedia_attached_files = filter_input( INPUT_POST, 'rtMedia_attached_files', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
|
177 |
+
// Check if files available.
|
178 |
+
if ( is_array( $rtmedia_attached_files ) && ! empty( $rtmedia_attached_files[0] ) ) {
|
179 |
+
// One url of image and other for anchor tag.
|
180 |
+
$values = count( $rtmedia_attached_files ) * 3;
|
181 |
+
}
|
182 |
+
return $values;
|
183 |
+
}
|
184 |
+
);
|
185 |
|
186 |
+
return bp_activity_filter_kses( $activity );
|
187 |
}
|
188 |
|
189 |
/**
|
app/main/controllers/activity/RTMediaBuddyPressActivity.php
CHANGED
@@ -339,6 +339,7 @@ class RTMediaBuddyPressActivity {
|
|
339 |
|
340 |
$rtmedia_attached_files = filter_input( INPUT_POST, 'rtMedia_attached_files', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
|
341 |
if ( is_array( $rtmedia_attached_files ) ) {
|
|
|
342 |
$media_obj = new RTMediaModel();
|
343 |
//Credit faisal : https://gist.github.com/faishal/c4306ae7267fff976465
|
344 |
$in_str_arr = array_fill( 0, count( $rtmedia_attached_files ), '%d' );
|
@@ -437,6 +438,15 @@ class RTMediaBuddyPressActivity {
|
|
437 |
}
|
438 |
|
439 |
function bp_after_activity_post_form() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
440 |
$request_uri = rtm_get_server_var( 'REQUEST_URI', 'FILTER_SANITIZE_URL' );
|
441 |
$url = rtmedia_get_upload_url( $request_uri );
|
442 |
if ( rtmedia_is_uploader_view_allowed( true, 'activity' ) ) {
|
@@ -856,6 +866,7 @@ class RTMediaBuddyPressActivity {
|
|
856 |
}
|
857 |
|
858 |
// create BuddyPress activity
|
|
|
859 |
$activity_id = bp_activity_add( $activity_args );
|
860 |
|
861 |
/* save the profile activity id in the media meta */
|
339 |
|
340 |
$rtmedia_attached_files = filter_input( INPUT_POST, 'rtMedia_attached_files', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
|
341 |
if ( is_array( $rtmedia_attached_files ) ) {
|
342 |
+
bp_activity_update_meta( $activity_id, 'bp_activity_text', bp_activity_filter_kses( $content ) );
|
343 |
$media_obj = new RTMediaModel();
|
344 |
//Credit faisal : https://gist.github.com/faishal/c4306ae7267fff976465
|
345 |
$in_str_arr = array_fill( 0, count( $rtmedia_attached_files ), '%d' );
|
438 |
}
|
439 |
|
440 |
function bp_after_activity_post_form() {
|
441 |
+
|
442 |
+
/**
|
443 |
+
* Filter to enable/disable media upload from the activity.
|
444 |
+
*
|
445 |
+
* @param bool Default true to enable activity media upload false to disable activity media upload.
|
446 |
+
*/
|
447 |
+
if ( ! apply_filters( 'rtmedia_enable_activity_media_upload', true ) ) {
|
448 |
+
return;
|
449 |
+
}
|
450 |
$request_uri = rtm_get_server_var( 'REQUEST_URI', 'FILTER_SANITIZE_URL' );
|
451 |
$url = rtmedia_get_upload_url( $request_uri );
|
452 |
if ( rtmedia_is_uploader_view_allowed( true, 'activity' ) ) {
|
866 |
}
|
867 |
|
868 |
// create BuddyPress activity
|
869 |
+
remove_filter( 'bp_activity_content_before_save', array( $this, 'bp_activity_content_before_save' ) );
|
870 |
$activity_id = bp_activity_add( $activity_args );
|
871 |
|
872 |
/* save the profile activity id in the media meta */
|
app/main/controllers/media/RTMediaAlbum.php
CHANGED
@@ -26,7 +26,7 @@ class RTMediaAlbum {
|
|
26 |
*/
|
27 |
public function __construct() {
|
28 |
add_action( 'init', array( &$this, 'register_post_types' ), 12 );
|
29 |
-
add_action( 'init', array( &$this, 'rtmedia_album_custom_post_status', 13 )
|
30 |
$this->media = new RTMediaMedia();
|
31 |
}
|
32 |
|
26 |
*/
|
27 |
public function __construct() {
|
28 |
add_action( 'init', array( &$this, 'register_post_types' ), 12 );
|
29 |
+
add_action( 'init', array( &$this, 'rtmedia_album_custom_post_status' ), 13 );
|
30 |
$this->media = new RTMediaMedia();
|
31 |
}
|
32 |
|
app/main/controllers/media/RTMediaFeatured.php
CHANGED
@@ -30,7 +30,7 @@ class RTMediaFeatured extends RTMediaUserInteraction {
|
|
30 |
'single' => true,
|
31 |
'repeatable' => false,
|
32 |
'undoable' => true,
|
33 |
-
'icon_class' => 'dashicons dashicons-star-filled
|
34 |
);
|
35 |
|
36 |
$this->user_id = $user_id;
|
30 |
'single' => true,
|
31 |
'repeatable' => false,
|
32 |
'undoable' => true,
|
33 |
+
'icon_class' => 'dashicons dashicons-star-filled',
|
34 |
);
|
35 |
|
36 |
$this->user_id = $user_id;
|
app/main/controllers/media/RTMediaGalleryItemAction.php
CHANGED
@@ -60,11 +60,11 @@ class RTMediaGalleryItemAction {
|
|
60 |
<div class='rtmedia-gallery-item-actions'>
|
61 |
<a href="<?php rtmedia_permalink(); ?>edit" class='no-popup' target='_blank'
|
62 |
title='<?php esc_attr_e( 'Edit this media', 'buddypress-media' ); ?>'>
|
63 |
-
<i class='dashicons dashicons-edit
|
64 |
</a>
|
65 |
<a href="#" class="no-popup rtm-delete-media"
|
66 |
title='<?php esc_attr_e( 'Delete this media', 'buddypress-media' ); ?>'>
|
67 |
-
<i class='dashicons dashicons-trash
|
68 |
</a>
|
69 |
</div>
|
70 |
<?php
|
@@ -77,7 +77,7 @@ class RTMediaGalleryItemAction {
|
|
77 |
$context_id = $media_array->context_id;
|
78 |
$user_id = get_current_user_id();
|
79 |
|
80 |
-
$media_array->media_actions = "<div class='rtmedia-gallery-item-actions'><a href='" . esc_url( $media_array->rt_permalink ) . "edit' class='no-popup' target='_blank' title='" . esc_attr__( 'Edit this media', 'buddypress-media' ) . "'><i class='dashicons dashicons-edit
|
81 |
if ( ! ( is_rt_admin() || ( function_exists( 'groups_is_user_mod' ) && groups_is_user_mod( $user_id, $context_id ) ) || intval( $media_array->media_author ) === get_current_user_id() ) ) {
|
82 |
$media_array->media_actions = '';
|
83 |
}
|
60 |
<div class='rtmedia-gallery-item-actions'>
|
61 |
<a href="<?php rtmedia_permalink(); ?>edit" class='no-popup' target='_blank'
|
62 |
title='<?php esc_attr_e( 'Edit this media', 'buddypress-media' ); ?>'>
|
63 |
+
<i class='dashicons dashicons-edit'></i><?php esc_html_e( 'Edit', 'buddypress-media' ); ?>
|
64 |
</a>
|
65 |
<a href="#" class="no-popup rtm-delete-media"
|
66 |
title='<?php esc_attr_e( 'Delete this media', 'buddypress-media' ); ?>'>
|
67 |
+
<i class='dashicons dashicons-trash'></i><?php esc_html_e( 'Delete', 'buddypress-media' ); ?>
|
68 |
</a>
|
69 |
</div>
|
70 |
<?php
|
77 |
$context_id = $media_array->context_id;
|
78 |
$user_id = get_current_user_id();
|
79 |
|
80 |
+
$media_array->media_actions = "<div class='rtmedia-gallery-item-actions'><a href='" . esc_url( $media_array->rt_permalink ) . "edit' class='no-popup' target='_blank' title='" . esc_attr__( 'Edit this media', 'buddypress-media' ) . "'><i class='dashicons dashicons-edit'></i>" . esc_html__( 'Edit', 'buddypress-media' ) . "</a><a href='#' class='no-popup rtm-delete-media' title='" . esc_attr__( 'Delete this media', 'buddypress-media' ) . "' ><i class='dashicons dashicons-trash'></i>" . esc_html__( 'Delete', 'buddypress-media' ) . '</a></div>';
|
81 |
if ( ! ( is_rt_admin() || ( function_exists( 'groups_is_user_mod' ) && groups_is_user_mod( $user_id, $context_id ) ) || intval( $media_array->media_author ) === get_current_user_id() ) ) {
|
82 |
$media_array->media_actions = '';
|
83 |
}
|
app/main/controllers/media/RTMediaGroupFeatured.php
CHANGED
@@ -22,7 +22,7 @@ class RTMediaGroupFeatured extends RTMediaUserInteraction {
|
|
22 |
'single' => true,
|
23 |
'repeatable' => false,
|
24 |
'undoable' => true,
|
25 |
-
'icon_class' => 'dashicons dashicons-star-filled
|
26 |
);
|
27 |
|
28 |
$this->group_id = $group_id;
|
22 |
'single' => true,
|
23 |
'repeatable' => false,
|
24 |
'undoable' => true,
|
25 |
+
'icon_class' => 'dashicons dashicons-star-filled',
|
26 |
);
|
27 |
|
28 |
$this->group_id = $group_id;
|
app/main/controllers/media/RTMediaLoginPopup.php
CHANGED
@@ -35,7 +35,7 @@ class RTMediaLoginPopup {
|
|
35 |
|
36 |
function rtmedia_add_upload_album_button_popup() {
|
37 |
if ( ! is_user_logged_in() ) {
|
38 |
-
echo '<span><a href="#rtmedia-login-register-modal" class="primary rtmedia-upload-media-link rtmedia-modal-link" id="rtmedia-login-register-modal" title="' . apply_filters( 'rtm_album_upload_title_label', __( 'Upload Media', 'buddypress-media' ) ) . '"><i class="dashicons dashicons-upload
|
39 |
}
|
40 |
}
|
41 |
|
35 |
|
36 |
function rtmedia_add_upload_album_button_popup() {
|
37 |
if ( ! is_user_logged_in() ) {
|
38 |
+
echo '<span><a href="#rtmedia-login-register-modal" class="primary rtmedia-upload-media-link rtmedia-modal-link" id="rtmedia-login-register-modal" title="' . apply_filters( 'rtm_album_upload_title_label', __( 'Upload Media', 'buddypress-media' ) ) . '"><i class="dashicons dashicons-upload"></i>' . apply_filters( 'rtm_album_upload_label', __( 'Upload', 'buddypress-media' ) ) . '</a></span>';
|
39 |
}
|
40 |
}
|
41 |
|
app/main/controllers/media/RTMediaMedia.php
CHANGED
@@ -439,7 +439,7 @@ class RTMediaMedia {
|
|
439 |
}
|
440 |
}
|
441 |
}
|
442 |
-
if ( ! $core ) {
|
443 |
wp_delete_attachment( $media[0]->media_id, true );
|
444 |
}
|
445 |
$status = $this->model->delete( array( 'id' => $id ) );
|
@@ -712,7 +712,7 @@ class RTMediaMedia {
|
|
712 |
$activity_content = $activity->create_activity_html();
|
713 |
$user = get_userdata( $media->media_author );
|
714 |
$username = '<a href="' . esc_url( get_rtmedia_user_link( $media->media_author ) ) . '">' . esc_html( $user->display_name ) . '</a>';
|
715 |
-
$count = count( $id );
|
716 |
$media_const = 'RTMEDIA_' . strtoupper( $media->media_type );
|
717 |
if ( $count > 1 ) {
|
718 |
$media_const .= '_PLURAL';
|
439 |
}
|
440 |
}
|
441 |
}
|
442 |
+
if ( ! $core && ! is_admin() ) {
|
443 |
wp_delete_attachment( $media[0]->media_id, true );
|
444 |
}
|
445 |
$status = $this->model->delete( array( 'id' => $id ) );
|
712 |
$activity_content = $activity->create_activity_html();
|
713 |
$user = get_userdata( $media->media_author );
|
714 |
$username = '<a href="' . esc_url( get_rtmedia_user_link( $media->media_author ) ) . '">' . esc_html( $user->display_name ) . '</a>';
|
715 |
+
$count = is_array( $id ) ? count( $id ) : 1 ;
|
716 |
$media_const = 'RTMEDIA_' . strtoupper( $media->media_type );
|
717 |
if ( $count > 1 ) {
|
718 |
$media_const .= '_PLURAL';
|
app/main/controllers/media/RTMediaTags.php
CHANGED
@@ -77,11 +77,14 @@ class RTMediaTags {
|
|
77 |
|
78 |
$tagwriter->tag_data = $this->data;
|
79 |
|
80 |
-
// write tags
|
81 |
-
|
82 |
-
|
83 |
-
|
|
|
84 |
throw new Exception( implode( ' : ', $tagwriter->errors ) );
|
|
|
|
|
85 |
}
|
86 |
}
|
87 |
|
@@ -145,7 +148,10 @@ class RTMediaTags {
|
|
145 |
if ( isset( $this->duration_info[ $key ] ) ) {
|
146 |
return $this->duration_info[ $key ];
|
147 |
} else {
|
148 |
-
|
|
|
|
|
|
|
149 |
}
|
150 |
}
|
151 |
}
|
77 |
|
78 |
$tagwriter->tag_data = $this->data;
|
79 |
|
80 |
+
// write tags.
|
81 |
+
try {
|
82 |
+
if ( $tagwriter->WriteTags() ) {
|
83 |
+
return true;
|
84 |
+
}
|
85 |
throw new Exception( implode( ' : ', $tagwriter->errors ) );
|
86 |
+
} catch ( Exception $e ) {
|
87 |
+
return new WP_Error( 'tag_write_error', $e->getMessage() );
|
88 |
}
|
89 |
}
|
90 |
|
148 |
if ( isset( $this->duration_info[ $key ] ) ) {
|
149 |
return $this->duration_info[ $key ];
|
150 |
} else {
|
151 |
+
if ( ! empty( $this->data[ $key ] ) && ! empty( $this->data[ $key ][0] ) ) {
|
152 |
+
return $this->data[ $key ][0];
|
153 |
+
}
|
154 |
+
return null;
|
155 |
}
|
156 |
}
|
157 |
}
|
app/main/controllers/media/RTMediaUserInteraction.php
CHANGED
@@ -215,8 +215,9 @@ class RTMediaUserInteraction {
|
|
215 |
$icon = "<i class='" . esc_attr( $this->icon_class ) . "'></i>";
|
216 |
}
|
217 |
$button_start = '<form action="' . esc_url( $link ) . '">';
|
|
|
218 |
$button = '<button type="submit" id="rtmedia-' . esc_attr( $this->action ) . '-button-' . esc_attr( $this->media->id ) . '" class="rtmedia-' . esc_attr( $this->action )
|
219 |
-
|
220 |
|
221 |
//filter the button as required
|
222 |
$button = apply_filters( 'rtmedia_' . $this->action . '_button_filter', $button );
|
215 |
$icon = "<i class='" . esc_attr( $this->icon_class ) . "'></i>";
|
216 |
}
|
217 |
$button_start = '<form action="' . esc_url( $link ) . '">';
|
218 |
+
$button_label = apply_filters( 'rtmedia_' . $this->action . '_label_text', $this->label );
|
219 |
$button = '<button type="submit" id="rtmedia-' . esc_attr( $this->action ) . '-button-' . esc_attr( $this->media->id ) . '" class="rtmedia-' . esc_attr( $this->action )
|
220 |
+
. ' rtmedia-action-buttons button' . esc_attr( $disabled ) . '" title="' . esc_attr( $button_label ) . '">' . $icon . '<span>' . esc_html( $button_label ) . '</span></button>';
|
221 |
|
222 |
//filter the button as required
|
223 |
$button = apply_filters( 'rtmedia_' . $this->action . '_button_filter', $button );
|
app/main/controllers/template/rtmedia-actions.php
CHANGED
@@ -51,7 +51,7 @@ function rtmedia_image_editor_title( $type = 'photo' ) {
|
|
51 |
global $rtmedia_query;
|
52 |
|
53 |
if ( isset( $rtmedia_query->media[0]->media_type ) && 'photo' === $rtmedia_query->media[0]->media_type && 'photo' === $type ) {
|
54 |
-
echo '<li><a href="#panel2" class="rtmedia-modify-image"><i class="dashicons dashicons-format-image
|
55 |
}
|
56 |
|
57 |
}
|
@@ -150,7 +150,7 @@ function rtmedia_gallery_options() {
|
|
150 |
if ( ! empty( $options ) ) {
|
151 |
$options_start .= '<div class="click-nav rtm-media-options-list" id="rtm-media-options-list">
|
152 |
<div class="no-js">
|
153 |
-
<div class="clicker rtmedia-action-buttons"><i class="dashicons dashicons-admin-generic
|
154 |
<ul class="rtm-options">';
|
155 |
|
156 |
foreach ( $options as $action ) {
|
@@ -316,11 +316,11 @@ function add_upload_button() {
|
|
316 |
$upload_string = apply_filters( 'rtmedia_upload_button_string', __( 'Upload', 'buddypress-media' ) );
|
317 |
|
318 |
if ( function_exists( 'bp_is_user' ) && bp_is_user() && function_exists( 'bp_displayed_user_id' ) && bp_displayed_user_id() === get_current_user_id() ) {
|
319 |
-
echo '<span class="primary rtmedia-upload-media-link" id="rtm_show_upload_ui" title="' . apply_filters( 'rtm_gallery_upload_title_label', __( 'Upload Media', 'buddypress-media' ) ) . '"><i class="dashicons dashicons-upload
|
320 |
} else {
|
321 |
if ( function_exists( 'bp_is_group' ) && bp_is_group() ) {
|
322 |
if ( can_user_upload_in_group() ) {
|
323 |
-
echo '<span class="rtmedia-upload-media-link primary" id="rtm_show_upload_ui" title="' . apply_filters( 'rtm_gallery_upload_title_label', __( 'Upload Media', 'buddypress-media' ) ) . '"><i class="dashicons dashicons-upload
|
324 |
}
|
325 |
}
|
326 |
}
|
@@ -950,8 +950,8 @@ function add_search_filter( $attr = null ) {
|
|
950 |
$html .= '</select>';
|
951 |
}
|
952 |
|
953 |
-
$html .= "<span id='media_search_remove' class='media_search_remove search_option'><i class='dashicons dashicons-no
|
954 |
-
$html .= "<button type='submit' id='media_search' class='search_option'><i class='dashicons dashicons-search
|
955 |
$html .= '</form>';
|
956 |
|
957 |
/**
|
51 |
global $rtmedia_query;
|
52 |
|
53 |
if ( isset( $rtmedia_query->media[0]->media_type ) && 'photo' === $rtmedia_query->media[0]->media_type && 'photo' === $type ) {
|
54 |
+
echo '<li><a href="#panel2" class="rtmedia-modify-image"><i class="dashicons dashicons-format-image"></i>' . esc_html__( 'Image', 'buddypress-media' ) . '</a></li>';
|
55 |
}
|
56 |
|
57 |
}
|
150 |
if ( ! empty( $options ) ) {
|
151 |
$options_start .= '<div class="click-nav rtm-media-options-list" id="rtm-media-options-list">
|
152 |
<div class="no-js">
|
153 |
+
<div class="clicker rtmedia-action-buttons"><i class="dashicons dashicons-admin-generic"></i>' . apply_filters( 'rtm_gallery_option_label', __( 'Options', 'buddypress-media' ) ) . '</div>
|
154 |
<ul class="rtm-options">';
|
155 |
|
156 |
foreach ( $options as $action ) {
|
316 |
$upload_string = apply_filters( 'rtmedia_upload_button_string', __( 'Upload', 'buddypress-media' ) );
|
317 |
|
318 |
if ( function_exists( 'bp_is_user' ) && bp_is_user() && function_exists( 'bp_displayed_user_id' ) && bp_displayed_user_id() === get_current_user_id() ) {
|
319 |
+
echo '<span class="primary rtmedia-upload-media-link" id="rtm_show_upload_ui" title="' . apply_filters( 'rtm_gallery_upload_title_label', __( 'Upload Media', 'buddypress-media' ) ) . '"><i class="dashicons dashicons-upload"></i>' . apply_filters( 'rtm_gallery_upload_label', __( 'Upload', 'buddypress-media' ) ) . '</span>';
|
320 |
} else {
|
321 |
if ( function_exists( 'bp_is_group' ) && bp_is_group() ) {
|
322 |
if ( can_user_upload_in_group() ) {
|
323 |
+
echo '<span class="rtmedia-upload-media-link primary" id="rtm_show_upload_ui" title="' . apply_filters( 'rtm_gallery_upload_title_label', __( 'Upload Media', 'buddypress-media' ) ) . '"><i class="dashicons dashicons-upload"></i>' . apply_filters( 'rtm_gallery_upload_label', __( 'Upload', 'buddypress-media' ) ) . '</span>';
|
324 |
}
|
325 |
}
|
326 |
}
|
950 |
$html .= '</select>';
|
951 |
}
|
952 |
|
953 |
+
$html .= "<span id='media_search_remove' class='media_search_remove search_option'><i class='dashicons dashicons-no'></i></span>";
|
954 |
+
$html .= "<button type='submit' id='media_search' class='search_option'><i class='dashicons dashicons-search'></i></button>";
|
955 |
$html .= '</form>';
|
956 |
|
957 |
/**
|
app/main/controllers/template/rtmedia-filters.php
CHANGED
@@ -47,7 +47,7 @@ function rtmedia_create_album( $options ) {
|
|
47 |
if ( true === $display ) {
|
48 |
add_action( 'rtmedia_before_media_gallery', 'rtmedia_create_album_modal' );
|
49 |
|
50 |
-
$options[] = "<a href='#rtmedia-create-album-modal' class='rtmedia-reveal-modal rtmedia-modal-link' title='" . esc_attr__( 'Create New Album', 'buddypress-media' ) . "'><i class='dashicons dashicons-plus-alt
|
51 |
}
|
52 |
|
53 |
return $options;
|
@@ -79,8 +79,8 @@ function rtmedia_album_edit( $options ) {
|
|
79 |
|
80 |
if ( isset( $rtmedia_query->media_query ) && isset( $rtmedia_query->media_query['album_id'] ) && ! in_array( intval( $rtmedia_query->media_query['album_id'] ), array_map( 'intval', rtmedia_get_site_option( 'rtmedia-global-albums' ) ), true ) ) {
|
81 |
if ( rtmedia_is_album_editable() || is_rt_admin() ) {
|
82 |
-
$options[] = "<a href='edit/' class='rtmedia-edit' title='" . esc_attr__( 'Edit Album', 'buddypress-media' ) . "' ><i class='
|
83 |
-
$options[] = '<form method="post" class="album-delete-form rtmedia-inline" action="delete/">' . wp_nonce_field( 'rtmedia_delete_album_' . $rtmedia_query->media_query['album_id'], 'rtmedia_delete_album_nonce' ) . '<button type="submit" name="album-delete" class="rtmedia-delete-album" title="' . esc_attr__( 'Delete Album', 'buddypress-media' ) . '"><i class="dashicons dashicons-trash
|
84 |
|
85 |
if ( is_rtmedia_group_album() ) {
|
86 |
$album_list = rtmedia_group_album_list();
|
@@ -282,7 +282,8 @@ function replace_src_with_transcoded_file_url( $html, $rtmedia_media ) {
|
|
282 |
$final_file_url = wp_get_attachment_url( $attachment_id );
|
283 |
}
|
284 |
|
285 |
-
|
|
|
286 |
|
287 |
}
|
288 |
|
@@ -815,20 +816,6 @@ function rtmedia_model_query_columns( $columns ) {
|
|
815 |
|
816 |
add_filter( 'rtmedia-model-query-columns', 'rtmedia_model_query_columns', 10, 1 );
|
817 |
|
818 |
-
function rtmedia_comment_max_links_callback( $values, $option = '' ) {
|
819 |
-
$new_values = $values;
|
820 |
-
if ( apply_filters( 'rtmedia_comment_max_links', true ) && 'comment_max_links' == $option ) {
|
821 |
-
$rtmedia_attached_files = filter_input( INPUT_POST, 'rtMedia_attached_files', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
|
822 |
-
if ( is_array( $rtmedia_attached_files ) && ! empty( $rtmedia_attached_files[0] ) ) {
|
823 |
-
if ( $new_values < 5 ) {
|
824 |
-
$new_values = 5;
|
825 |
-
}
|
826 |
-
}
|
827 |
-
}
|
828 |
-
return $new_values;
|
829 |
-
}
|
830 |
-
add_filter( 'option_comment_max_links', 'rtmedia_comment_max_links_callback', 10, 2 );
|
831 |
-
|
832 |
/**
|
833 |
* add link for @mentions of the username in the comment or the activity section after the media delete or media is trancoder
|
834 |
*/
|
47 |
if ( true === $display ) {
|
48 |
add_action( 'rtmedia_before_media_gallery', 'rtmedia_create_album_modal' );
|
49 |
|
50 |
+
$options[] = "<a href='#rtmedia-create-album-modal' class='rtmedia-reveal-modal rtmedia-modal-link' title='" . esc_attr__( 'Create New Album', 'buddypress-media' ) . "'><i class='dashicons dashicons-plus-alt'></i>" . esc_html__( 'Add Album', 'buddypress-media' ) . '</a>';
|
51 |
}
|
52 |
|
53 |
return $options;
|
79 |
|
80 |
if ( isset( $rtmedia_query->media_query ) && isset( $rtmedia_query->media_query['album_id'] ) && ! in_array( intval( $rtmedia_query->media_query['album_id'] ), array_map( 'intval', rtmedia_get_site_option( 'rtmedia-global-albums' ) ), true ) ) {
|
81 |
if ( rtmedia_is_album_editable() || is_rt_admin() ) {
|
82 |
+
$options[] = "<a href='edit/' class='rtmedia-edit' title='" . esc_attr__( 'Edit Album', 'buddypress-media' ) . "' ><i class='dashicons dashicons-edit'></i>" . esc_html__( 'Edit Album', 'buddypress-media' ) . '</a>';
|
83 |
+
$options[] = '<form method="post" class="album-delete-form rtmedia-inline" action="delete/">' . wp_nonce_field( 'rtmedia_delete_album_' . $rtmedia_query->media_query['album_id'], 'rtmedia_delete_album_nonce' ) . '<button type="submit" name="album-delete" class="rtmedia-delete-album" title="' . esc_attr__( 'Delete Album', 'buddypress-media' ) . '"><i class="dashicons dashicons-trash"></i>' . esc_html__( 'Delete Album', 'buddypress-media' ) . '</button></form>';
|
84 |
|
85 |
if ( is_rtmedia_group_album() ) {
|
86 |
$album_list = rtmedia_group_album_list();
|
282 |
$final_file_url = wp_get_attachment_url( $attachment_id );
|
283 |
}
|
284 |
|
285 |
+
//Add timestamp to resolve conflict with cache media.
|
286 |
+
return preg_replace( '/src=["]([^"]+)["]/', 'src="' . $final_file_url . '?' . time() . '"', $html );
|
287 |
|
288 |
}
|
289 |
|
816 |
|
817 |
add_filter( 'rtmedia-model-query-columns', 'rtmedia_model_query_columns', 10, 1 );
|
818 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
819 |
/**
|
820 |
* add link for @mentions of the username in the comment or the activity section after the media delete or media is trancoder
|
821 |
*/
|
app/main/controllers/template/rtmedia-functions.php
CHANGED
@@ -547,8 +547,11 @@ function rtmedia_media( $size_flag = true, $echo = true, $media_size = 'rt_media
|
|
547 |
* Used `set_url_scheme` because `esc_url` breaks the image if there is special characters are there into image name.
|
548 |
* Added by checking the code from "wp-admin/includes/media.php:2740".
|
549 |
* Because in media library, it was not breaking.
|
|
|
|
|
550 |
*/
|
551 |
-
$html = "<img src='" . set_url_scheme( $src[0] ) . "' alt='" . esc_attr( $rtmedia_media->post_name ) . "' />";
|
|
|
552 |
} elseif ( 'video' === $rtmedia_media->media_type ) {
|
553 |
$youtube_url = get_rtmedia_meta( $rtmedia_media->id, 'video_url_uploaded_from' );
|
554 |
$height = $rtmedia->options['defaultSizes_video_singlePlayer_height'];
|
@@ -691,6 +694,9 @@ function rtmedia_image( $size = 'rt_media_thumbnail', $id = false, $recho = true
|
|
691 |
|
692 |
$src = apply_filters( 'rtmedia_media_thumb', $src, $media_object->id, $media_object->media_type );
|
693 |
|
|
|
|
|
|
|
694 |
if ( true === $recho ) {
|
695 |
echo set_url_scheme( $src );
|
696 |
} else {
|
@@ -1312,7 +1318,7 @@ function rmedia_single_comment( $comment, $count = false, $i = false ) {
|
|
1312 |
$html .= '<div class="rtmedia-comment-extra">' . apply_filters( 'rtmedia_comment_extra', '', $comment ) . '</div>';
|
1313 |
|
1314 |
if ( is_rt_admin() || ( isset( $comment['user_id'] ) && ( get_current_user_id() === intval( $comment['user_id'] ) || intval( $rtmedia_media->media_author ) === get_current_user_id() ) ) || apply_filters( 'rtmedia_allow_comment_delete', false ) ) { // show delete button for comment author and admins
|
1315 |
-
$html .= '<i data-id="' . esc_attr( $comment['comment_ID'] ) . '" class = "rtmedia-delete-comment dashicons dashicons-no-alt
|
1316 |
}
|
1317 |
|
1318 |
$html .= '<div class="clear"></div></div></div></li>';
|
@@ -2880,7 +2886,7 @@ function show_rtmedia_like_counts() {
|
|
2880 |
}
|
2881 |
?>
|
2882 |
<div class='rtmedia-like-info <?php echo $class; ?>'>
|
2883 |
-
<i class="
|
2884 |
<span class="rtmedia-like-counter-wrap">
|
2885 |
<?php
|
2886 |
if ( class_exists( 'RTMediaLike' ) && function_exists( 'rtmedia_who_like_html' ) ) {
|
@@ -3063,27 +3069,27 @@ function get_rtmedia_privacy_symbol( $rtmedia_id = false ) {
|
|
3063 |
switch ( $actions[0]->privacy ) {
|
3064 |
case 0: // public
|
3065 |
$title = esc_html__( 'Public', 'buddypress-media' );
|
3066 |
-
$icon = 'dashicons dashicons-admin-site
|
3067 |
|
3068 |
break;
|
3069 |
case 20: // users
|
3070 |
$title = esc_html__( 'All members', 'buddypress-media' );
|
3071 |
-
$icon = 'dashicons dashicons-groups
|
3072 |
|
3073 |
break;
|
3074 |
case 40: // friends
|
3075 |
$title = esc_html__( 'Your friends', 'buddypress-media' );
|
3076 |
-
$icon = 'dashicons dashicons-networking
|
3077 |
|
3078 |
break;
|
3079 |
case 60: // private
|
3080 |
$title = esc_html__( 'Only you', 'buddypress-media' );
|
3081 |
-
$icon = 'dashicons dashicons-lock
|
3082 |
|
3083 |
break;
|
3084 |
case 80: // private
|
3085 |
$title = esc_html__( 'Blocked temporarily', 'buddypress-media' );
|
3086 |
-
$icon = 'dashicons dashicons-dismiss
|
3087 |
|
3088 |
break;
|
3089 |
}
|
547 |
* Used `set_url_scheme` because `esc_url` breaks the image if there is special characters are there into image name.
|
548 |
* Added by checking the code from "wp-admin/includes/media.php:2740".
|
549 |
* Because in media library, it was not breaking.
|
550 |
+
*
|
551 |
+
* Add timestamp to resolve conflict with cache image.
|
552 |
*/
|
553 |
+
$html = "<img src='" . set_url_scheme( $src[0]. '?' . time() ) . "' alt='" . esc_attr( $rtmedia_media->post_name ) . "' />";
|
554 |
+
|
555 |
} elseif ( 'video' === $rtmedia_media->media_type ) {
|
556 |
$youtube_url = get_rtmedia_meta( $rtmedia_media->id, 'video_url_uploaded_from' );
|
557 |
$height = $rtmedia->options['defaultSizes_video_singlePlayer_height'];
|
694 |
|
695 |
$src = apply_filters( 'rtmedia_media_thumb', $src, $media_object->id, $media_object->media_type );
|
696 |
|
697 |
+
//Added timestamp because conflict with cache image.
|
698 |
+
$src = $src . '?' . time();
|
699 |
+
|
700 |
if ( true === $recho ) {
|
701 |
echo set_url_scheme( $src );
|
702 |
} else {
|
1318 |
$html .= '<div class="rtmedia-comment-extra">' . apply_filters( 'rtmedia_comment_extra', '', $comment ) . '</div>';
|
1319 |
|
1320 |
if ( is_rt_admin() || ( isset( $comment['user_id'] ) && ( get_current_user_id() === intval( $comment['user_id'] ) || intval( $rtmedia_media->media_author ) === get_current_user_id() ) ) || apply_filters( 'rtmedia_allow_comment_delete', false ) ) { // show delete button for comment author and admins
|
1321 |
+
$html .= '<i data-id="' . esc_attr( $comment['comment_ID'] ) . '" class = "rtmedia-delete-comment dashicons dashicons-no-alt" title="' . esc_attr__( 'Delete Comment', 'buddypress-media' ) . '"></i>';
|
1322 |
}
|
1323 |
|
1324 |
$html .= '<div class="clear"></div></div></div></li>';
|
2886 |
}
|
2887 |
?>
|
2888 |
<div class='rtmedia-like-info <?php echo $class; ?>'>
|
2889 |
+
<i class="dashicons dashicons-thumbs-up"></i>
|
2890 |
<span class="rtmedia-like-counter-wrap">
|
2891 |
<?php
|
2892 |
if ( class_exists( 'RTMediaLike' ) && function_exists( 'rtmedia_who_like_html' ) ) {
|
3069 |
switch ( $actions[0]->privacy ) {
|
3070 |
case 0: // public
|
3071 |
$title = esc_html__( 'Public', 'buddypress-media' );
|
3072 |
+
$icon = 'dashicons dashicons-admin-site';
|
3073 |
|
3074 |
break;
|
3075 |
case 20: // users
|
3076 |
$title = esc_html__( 'All members', 'buddypress-media' );
|
3077 |
+
$icon = 'dashicons dashicons-groups';
|
3078 |
|
3079 |
break;
|
3080 |
case 40: // friends
|
3081 |
$title = esc_html__( 'Your friends', 'buddypress-media' );
|
3082 |
+
$icon = 'dashicons dashicons-networking';
|
3083 |
|
3084 |
break;
|
3085 |
case 60: // private
|
3086 |
$title = esc_html__( 'Only you', 'buddypress-media' );
|
3087 |
+
$icon = 'dashicons dashicons-lock';
|
3088 |
|
3089 |
break;
|
3090 |
case 80: // private
|
3091 |
$title = esc_html__( 'Blocked temporarily', 'buddypress-media' );
|
3092 |
+
$icon = 'dashicons dashicons-dismiss';
|
3093 |
|
3094 |
break;
|
3095 |
}
|
app/main/controllers/upload/RTMediaUploadView.php
CHANGED
@@ -48,10 +48,10 @@ class RTMediaUploadView {
|
|
48 |
} elseif ( is_rtmedia_album_enable() && $rtmedia_query && is_rtmedia_gallery() ) {
|
49 |
|
50 |
if ( isset( $rtmedia_query->query['context'] ) && 'profile' === $rtmedia_query->query['context'] ) {
|
51 |
-
$album = '<span> <label> <i class="dashicons dashicons-format-gallery
|
52 |
}
|
53 |
if ( isset( $rtmedia_query->query['context'] ) && 'group' === $rtmedia_query->query['context'] ) {
|
54 |
-
$album = '<span> <label> <i class="dashicons dashicons-format-gallery
|
55 |
}
|
56 |
}
|
57 |
}
|
@@ -94,7 +94,7 @@ class RTMediaUploadView {
|
|
94 |
$up_privacy = new RTMediaPrivacy( false );
|
95 |
$up_privacy = $up_privacy->select_privacy_ui( false, 'rtSelectPrivacy' );
|
96 |
if ( $up_privacy ) {
|
97 |
-
$privacy = "<span> <label for='privacy'> <i class='dashicons dashicons-visibility
|
98 |
}
|
99 |
}
|
100 |
}
|
@@ -106,7 +106,7 @@ class RTMediaUploadView {
|
|
106 |
'content' => '<div class="rtm-upload-tab-content" data-id="rtm-upload-tab">'
|
107 |
. apply_filters( 'rtmedia_uploader_before_select_files', '' )
|
108 |
. '<div class="rtm-select-files"><input id="' . apply_filters( 'rtmedia_upload_button_id', 'rtMedia-upload-button' ) . '" value="' . esc_attr__( 'Select your files', 'buddypress-media' ) . '" type="button" class="rtmedia-upload-input rtmedia-file" />'
|
109 |
-
. '<span class="rtm-seperator">' . esc_html__( 'or', 'buddypress-media' ) . '</span><span class="drag-drop-info">' . esc_html__( 'Drop your files here', 'buddypress-media' ) . '</span> <i class="rtm-file-size-limit
|
110 |
. apply_filters( 'rtmedia_uploader_after_select_files', '' )
|
111 |
. '</div>',
|
112 |
),
|
48 |
} elseif ( is_rtmedia_album_enable() && $rtmedia_query && is_rtmedia_gallery() ) {
|
49 |
|
50 |
if ( isset( $rtmedia_query->query['context'] ) && 'profile' === $rtmedia_query->query['context'] ) {
|
51 |
+
$album = '<span> <label> <i class="dashicons dashicons-format-gallery"></i>' . esc_html__( 'Album', 'buddypress-media' ) . ': </label><select name="album" class="rtmedia-user-album-list">' . rtmedia_user_album_list() . '</select></span>';
|
52 |
}
|
53 |
if ( isset( $rtmedia_query->query['context'] ) && 'group' === $rtmedia_query->query['context'] ) {
|
54 |
+
$album = '<span> <label> <i class="dashicons dashicons-format-gallery"></i>' . esc_html__( 'Album', 'buddypress-media' ) . ': </label><select name="album" class="rtmedia-user-album-list">' . rtmedia_group_album_list() . '</select></span>';
|
55 |
}
|
56 |
}
|
57 |
}
|
94 |
$up_privacy = new RTMediaPrivacy( false );
|
95 |
$up_privacy = $up_privacy->select_privacy_ui( false, 'rtSelectPrivacy' );
|
96 |
if ( $up_privacy ) {
|
97 |
+
$privacy = "<span> <label for='privacy'> <i class='dashicons dashicons-visibility'></i>" . esc_html__( 'Privacy:', 'buddypress-media' ) . '</label>' . $up_privacy . '</span>';
|
98 |
}
|
99 |
}
|
100 |
}
|
106 |
'content' => '<div class="rtm-upload-tab-content" data-id="rtm-upload-tab">'
|
107 |
. apply_filters( 'rtmedia_uploader_before_select_files', '' )
|
108 |
. '<div class="rtm-select-files"><input id="' . apply_filters( 'rtmedia_upload_button_id', 'rtMedia-upload-button' ) . '" value="' . esc_attr__( 'Select your files', 'buddypress-media' ) . '" type="button" class="rtmedia-upload-input rtmedia-file" />'
|
109 |
+
. '<span class="rtm-seperator">' . esc_html__( 'or', 'buddypress-media' ) . '</span><span class="drag-drop-info">' . esc_html__( 'Drop your files here', 'buddypress-media' ) . '</span> <i class="rtm-file-size-limit dashicons dashicons-info"></i></div>'
|
110 |
. apply_filters( 'rtmedia_uploader_after_select_files', '' )
|
111 |
. '</div>',
|
112 |
),
|
index.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
Plugin Name: rtMedia for WordPress, BuddyPress and bbPress
|
4 |
Plugin URI: https://rtmedia.io/?utm_source=dashboard&utm_medium=plugin&utm_campaign=buddypress-media
|
5 |
Description: This plugin adds missing media rich features like photos, videos and audio uploading to BuddyPress which are essential if you are building social network, seriously!
|
6 |
-
Version: 4.5.
|
7 |
Author: rtCamp
|
8 |
Text Domain: buddypress-media
|
9 |
Author URI: http://rtcamp.com/?utm_source=dashboard&utm_medium=plugin&utm_campaign=buddypress-media
|
@@ -22,7 +22,7 @@ if ( ! defined( 'RTMEDIA_VERSION' ) ) {
|
|
22 |
* The version of the plugin
|
23 |
*
|
24 |
*/
|
25 |
-
define( 'RTMEDIA_VERSION', '4.5.
|
26 |
}
|
27 |
|
28 |
if ( ! defined( 'RTMEDIA_PATH' ) ) {
|
3 |
Plugin Name: rtMedia for WordPress, BuddyPress and bbPress
|
4 |
Plugin URI: https://rtmedia.io/?utm_source=dashboard&utm_medium=plugin&utm_campaign=buddypress-media
|
5 |
Description: This plugin adds missing media rich features like photos, videos and audio uploading to BuddyPress which are essential if you are building social network, seriously!
|
6 |
+
Version: 4.5.7
|
7 |
Author: rtCamp
|
8 |
Text Domain: buddypress-media
|
9 |
Author URI: http://rtcamp.com/?utm_source=dashboard&utm_medium=plugin&utm_campaign=buddypress-media
|
22 |
* The version of the plugin
|
23 |
*
|
24 |
*/
|
25 |
+
define( 'RTMEDIA_VERSION', '4.5.7' );
|
26 |
}
|
27 |
|
28 |
if ( ! defined( 'RTMEDIA_PATH' ) ) {
|
languages/buddypress-media.po
CHANGED
@@ -2,9 +2,9 @@
|
|
2 |
# This file is distributed under the same license as the rtMedia for WordPress, BuddyPress and bbPress package.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
-
"Project-Id-Version: rtMedia for WordPress, BuddyPress and bbPress 4.5.
|
6 |
"Report-Msgid-Bugs-To: https://rtmedia.io/support/\n"
|
7 |
-
"POT-Creation-Date: 2019-
|
8 |
"MIME-Version: 1.0\n"
|
9 |
"Content-Type: text/plain; charset=utf-8\n"
|
10 |
"Content-Transfer-Encoding: 8bit\n"
|
@@ -22,7 +22,7 @@ msgstr ""
|
|
22 |
"X-Poedit-SearchPath-0: .\n"
|
23 |
"X-Poedit-Bookmarks: \n"
|
24 |
"X-Textdomain-Support: yes\n"
|
25 |
-
"X-Generator: grunt-wp-
|
26 |
|
27 |
#: app/admin/RTMediaAdmin.php:148
|
28 |
msgid ""
|
2 |
# This file is distributed under the same license as the rtMedia for WordPress, BuddyPress and bbPress package.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
+
"Project-Id-Version: rtMedia for WordPress, BuddyPress and bbPress 4.5.7\n"
|
6 |
"Report-Msgid-Bugs-To: https://rtmedia.io/support/\n"
|
7 |
+
"POT-Creation-Date: 2019-06-10 12:30:20+00:00\n"
|
8 |
"MIME-Version: 1.0\n"
|
9 |
"Content-Type: text/plain; charset=utf-8\n"
|
10 |
"Content-Transfer-Encoding: 8bit\n"
|
22 |
"X-Poedit-SearchPath-0: .\n"
|
23 |
"X-Poedit-Bookmarks: \n"
|
24 |
"X-Textdomain-Support: yes\n"
|
25 |
+
"X-Generator: grunt-wp-i18n 1.0.3\n"
|
26 |
|
27 |
#: app/admin/RTMediaAdmin.php:148
|
28 |
msgid ""
|
lib/getid3/extension.cache.dbm.php
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
/////////////////////////////////////////////////////////////////
|
8 |
// //
|
9 |
// extension.cache.dbm.php - part of getID3() //
|
10 |
// Please see readme.txt for more information //
|
@@ -72,9 +72,37 @@
|
|
72 |
|
73 |
class getID3_cached_dbm extends getID3
|
74 |
{
|
75 |
-
|
76 |
-
|
77 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
|
79 |
// Check for dba extension
|
80 |
if (!extension_loaded('dba')) {
|
@@ -141,7 +169,9 @@ class getID3_cached_dbm extends getID3
|
|
141 |
|
142 |
|
143 |
|
144 |
-
|
|
|
|
|
145 |
public function __destruct() {
|
146 |
|
147 |
// Close dbm file
|
@@ -156,7 +186,11 @@ class getID3_cached_dbm extends getID3
|
|
156 |
|
157 |
|
158 |
|
159 |
-
|
|
|
|
|
|
|
|
|
160 |
public function clear_cache() {
|
161 |
|
162 |
// Close dbm file
|
@@ -178,8 +212,16 @@ class getID3_cached_dbm extends getID3
|
|
178 |
|
179 |
|
180 |
|
181 |
-
|
182 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
183 |
|
184 |
if (file_exists($filename)) {
|
185 |
|
@@ -199,7 +241,7 @@ class getID3_cached_dbm extends getID3
|
|
199 |
$result = parent::analyze($filename);
|
200 |
|
201 |
// Save result
|
202 |
-
if (file_exists($filename)) {
|
203 |
dba_insert($key, serialize($result), $this->dba);
|
204 |
}
|
205 |
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
|
|
8 |
// //
|
9 |
// extension.cache.dbm.php - part of getID3() //
|
10 |
// Please see readme.txt for more information //
|
72 |
|
73 |
class getID3_cached_dbm extends getID3
|
74 |
{
|
75 |
+
/**
|
76 |
+
* @var resource
|
77 |
+
*/
|
78 |
+
private $dba;
|
79 |
+
|
80 |
+
/**
|
81 |
+
* @var resource|bool
|
82 |
+
*/
|
83 |
+
private $lock;
|
84 |
+
|
85 |
+
/**
|
86 |
+
* @var string
|
87 |
+
*/
|
88 |
+
private $cache_type;
|
89 |
+
|
90 |
+
/**
|
91 |
+
* @var string
|
92 |
+
*/
|
93 |
+
private $dbm_filename;
|
94 |
+
|
95 |
+
/**
|
96 |
+
* constructor - see top of this file for cache type and cache_options
|
97 |
+
*
|
98 |
+
* @param string $cache_type
|
99 |
+
* @param string $dbm_filename
|
100 |
+
* @param string $lock_filename
|
101 |
+
*
|
102 |
+
* @throws Exception
|
103 |
+
* @throws getid3_exception
|
104 |
+
*/
|
105 |
+
public function __construct($cache_type, $dbm_filename, $lock_filename) {
|
106 |
|
107 |
// Check for dba extension
|
108 |
if (!extension_loaded('dba')) {
|
169 |
|
170 |
|
171 |
|
172 |
+
/**
|
173 |
+
* destructor
|
174 |
+
*/
|
175 |
public function __destruct() {
|
176 |
|
177 |
// Close dbm file
|
186 |
|
187 |
|
188 |
|
189 |
+
/**
|
190 |
+
* clear cache
|
191 |
+
*
|
192 |
+
* @throws Exception
|
193 |
+
*/
|
194 |
public function clear_cache() {
|
195 |
|
196 |
// Close dbm file
|
212 |
|
213 |
|
214 |
|
215 |
+
/**
|
216 |
+
* clear cache
|
217 |
+
*
|
218 |
+
* @param string $filename
|
219 |
+
* @param int $filesize
|
220 |
+
* @param string $original_filename
|
221 |
+
*
|
222 |
+
* @return mixed
|
223 |
+
*/
|
224 |
+
public function analyze($filename, $filesize=null, $original_filename='') {
|
225 |
|
226 |
if (file_exists($filename)) {
|
227 |
|
241 |
$result = parent::analyze($filename);
|
242 |
|
243 |
// Save result
|
244 |
+
if (isset($key) && file_exists($filename)) {
|
245 |
dba_insert($key, serialize($result), $this->dba);
|
246 |
}
|
247 |
|
lib/getid3/extension.cache.mysql.php
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
/////////////////////////////////////////////////////////////////
|
8 |
// //
|
9 |
// extension.cache.mysql.php - part of getID3() //
|
10 |
// Please see readme.txt for more information //
|
@@ -73,14 +73,35 @@
|
|
73 |
|
74 |
class getID3_cached_mysql extends getID3
|
75 |
{
|
76 |
-
|
77 |
-
|
|
|
78 |
private $cursor;
|
79 |
-
private $connection;
|
80 |
|
|
|
|
|
|
|
|
|
81 |
|
82 |
-
|
83 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
|
85 |
// Check for mysql support
|
86 |
if (!function_exists('mysql_pconnect')) {
|
@@ -124,7 +145,9 @@ class getID3_cached_mysql extends getID3
|
|
124 |
|
125 |
|
126 |
|
127 |
-
|
|
|
|
|
128 |
public function clear_cache() {
|
129 |
|
130 |
$this->cursor = mysql_query('DELETE FROM `'.mysql_real_escape_string($this->table).'`', $this->connection);
|
@@ -133,9 +156,18 @@ class getID3_cached_mysql extends getID3
|
|
133 |
|
134 |
|
135 |
|
136 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
public function analyze($filename, $filesize=null, $original_filename='') {
|
138 |
|
|
|
139 |
if (file_exists($filename)) {
|
140 |
|
141 |
// Short-hands
|
@@ -174,16 +206,20 @@ class getID3_cached_mysql extends getID3
|
|
174 |
|
175 |
|
176 |
|
177 |
-
|
|
|
|
|
|
|
|
|
178 |
private function create_table($drop=false) {
|
179 |
|
180 |
$SQLquery = 'CREATE TABLE IF NOT EXISTS `'.mysql_real_escape_string($this->table).'` (';
|
181 |
-
$SQLquery .= '`filename` VARCHAR(
|
182 |
$SQLquery .= ', `filesize` INT(11) NOT NULL DEFAULT \'0\'';
|
183 |
$SQLquery .= ', `filetime` INT(11) NOT NULL DEFAULT \'0\'';
|
184 |
$SQLquery .= ', `analyzetime` INT(11) NOT NULL DEFAULT \'0\'';
|
185 |
$SQLquery .= ', `value` LONGTEXT NOT NULL';
|
186 |
-
$SQLquery .= ', PRIMARY KEY (`filename`, `filesize`, `filetime`))
|
187 |
$this->cursor = mysql_query($SQLquery, $this->connection);
|
188 |
echo mysql_error($this->connection);
|
189 |
}
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
|
|
8 |
// //
|
9 |
// extension.cache.mysql.php - part of getID3() //
|
10 |
// Please see readme.txt for more information //
|
73 |
|
74 |
class getID3_cached_mysql extends getID3
|
75 |
{
|
76 |
+
/**
|
77 |
+
* @var resource
|
78 |
+
*/
|
79 |
private $cursor;
|
|
|
80 |
|
81 |
+
/**
|
82 |
+
* @var resource
|
83 |
+
*/
|
84 |
+
private $connection;
|
85 |
|
86 |
+
/**
|
87 |
+
* @var string
|
88 |
+
*/
|
89 |
+
private $table;
|
90 |
+
|
91 |
+
|
92 |
+
/**
|
93 |
+
* constructor - see top of this file for cache type and cache_options
|
94 |
+
*
|
95 |
+
* @param string $host
|
96 |
+
* @param string $database
|
97 |
+
* @param string $username
|
98 |
+
* @param string $password
|
99 |
+
* @param string $table
|
100 |
+
*
|
101 |
+
* @throws Exception
|
102 |
+
* @throws getid3_exception
|
103 |
+
*/
|
104 |
+
public function __construct($host, $database, $username, $password, $table='getid3_cache') {
|
105 |
|
106 |
// Check for mysql support
|
107 |
if (!function_exists('mysql_pconnect')) {
|
145 |
|
146 |
|
147 |
|
148 |
+
/**
|
149 |
+
* clear cache
|
150 |
+
*/
|
151 |
public function clear_cache() {
|
152 |
|
153 |
$this->cursor = mysql_query('DELETE FROM `'.mysql_real_escape_string($this->table).'`', $this->connection);
|
156 |
|
157 |
|
158 |
|
159 |
+
/**
|
160 |
+
* analyze file
|
161 |
+
*
|
162 |
+
* @param string $filename
|
163 |
+
* @param int $filesize
|
164 |
+
* @param string $original_filename
|
165 |
+
*
|
166 |
+
* @return mixed
|
167 |
+
*/
|
168 |
public function analyze($filename, $filesize=null, $original_filename='') {
|
169 |
|
170 |
+
$filetime = 0;
|
171 |
if (file_exists($filename)) {
|
172 |
|
173 |
// Short-hands
|
206 |
|
207 |
|
208 |
|
209 |
+
/**
|
210 |
+
* (re)create sql table
|
211 |
+
*
|
212 |
+
* @param bool $drop
|
213 |
+
*/
|
214 |
private function create_table($drop=false) {
|
215 |
|
216 |
$SQLquery = 'CREATE TABLE IF NOT EXISTS `'.mysql_real_escape_string($this->table).'` (';
|
217 |
+
$SQLquery .= '`filename` VARCHAR(990) NOT NULL DEFAULT \'\'';
|
218 |
$SQLquery .= ', `filesize` INT(11) NOT NULL DEFAULT \'0\'';
|
219 |
$SQLquery .= ', `filetime` INT(11) NOT NULL DEFAULT \'0\'';
|
220 |
$SQLquery .= ', `analyzetime` INT(11) NOT NULL DEFAULT \'0\'';
|
221 |
$SQLquery .= ', `value` LONGTEXT NOT NULL';
|
222 |
+
$SQLquery .= ', PRIMARY KEY (`filename`, `filesize`, `filetime`))';
|
223 |
$this->cursor = mysql_query($SQLquery, $this->connection);
|
224 |
echo mysql_error($this->connection);
|
225 |
}
|
lib/getid3/extension.cache.mysqli.php
ADDED
@@ -0,0 +1,220 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/////////////////////////////////////////////////////////////////
|
4 |
+
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// //
|
9 |
+
// extension.cache.mysqli.php - part of getID3() //
|
10 |
+
// Please see readme.txt for more information //
|
11 |
+
// //
|
12 |
+
/////////////////////////////////////////////////////////////////
|
13 |
+
// //
|
14 |
+
// This extension written by Allan Hansen <ahØartemis*dk> //
|
15 |
+
// Table name mod by Carlo Capocasa <calroØcarlocapocasa*com> //
|
16 |
+
// ///
|
17 |
+
/////////////////////////////////////////////////////////////////
|
18 |
+
|
19 |
+
|
20 |
+
/**
|
21 |
+
* This is a caching extension for getID3(). It works the exact same
|
22 |
+
* way as the getID3 class, but return cached information very fast
|
23 |
+
*
|
24 |
+
* Example: (see also demo.cache.mysql.php in /demo/)
|
25 |
+
*
|
26 |
+
* Normal getID3 usage (example):
|
27 |
+
*
|
28 |
+
* require_once 'getid3/getid3.php';
|
29 |
+
* $getID3 = new getID3;
|
30 |
+
* $getID3->encoding = 'UTF-8';
|
31 |
+
* $info1 = $getID3->analyze('file1.flac');
|
32 |
+
* $info2 = $getID3->analyze('file2.wv');
|
33 |
+
*
|
34 |
+
* getID3_cached usage:
|
35 |
+
*
|
36 |
+
* require_once 'getid3/getid3.php';
|
37 |
+
* require_once 'getid3/getid3/extension.cache.mysqli.php';
|
38 |
+
* // 5th parameter (tablename) is optional, default is 'getid3_cache'
|
39 |
+
* $getID3 = new getID3_cached_mysqli('localhost', 'database', 'username', 'password', 'tablename');
|
40 |
+
* $getID3->encoding = 'UTF-8';
|
41 |
+
* $info1 = $getID3->analyze('file1.flac');
|
42 |
+
* $info2 = $getID3->analyze('file2.wv');
|
43 |
+
*
|
44 |
+
*
|
45 |
+
* Supported Cache Types (this extension)
|
46 |
+
*
|
47 |
+
* SQL Databases:
|
48 |
+
*
|
49 |
+
* cache_type cache_options
|
50 |
+
* -------------------------------------------------------------------
|
51 |
+
* mysqli host, database, username, password
|
52 |
+
*
|
53 |
+
*
|
54 |
+
* DBM-Style Databases: (use extension.cache.dbm)
|
55 |
+
*
|
56 |
+
* cache_type cache_options
|
57 |
+
* -------------------------------------------------------------------
|
58 |
+
* gdbm dbm_filename, lock_filename
|
59 |
+
* ndbm dbm_filename, lock_filename
|
60 |
+
* db2 dbm_filename, lock_filename
|
61 |
+
* db3 dbm_filename, lock_filename
|
62 |
+
* db4 dbm_filename, lock_filename (PHP5 required)
|
63 |
+
*
|
64 |
+
* PHP must have write access to both dbm_filename and lock_filename.
|
65 |
+
*
|
66 |
+
*
|
67 |
+
* Recommended Cache Types
|
68 |
+
*
|
69 |
+
* Infrequent updates, many reads any DBM
|
70 |
+
* Frequent updates mysqli
|
71 |
+
*/
|
72 |
+
|
73 |
+
class getID3_cached_mysqli extends getID3
|
74 |
+
{
|
75 |
+
/**
|
76 |
+
* @var mysqli
|
77 |
+
*/
|
78 |
+
private $mysqli;
|
79 |
+
|
80 |
+
/**
|
81 |
+
* @var mysqli_result
|
82 |
+
*/
|
83 |
+
private $cursor;
|
84 |
+
|
85 |
+
/**
|
86 |
+
* @var string
|
87 |
+
*/
|
88 |
+
private $table;
|
89 |
+
|
90 |
+
|
91 |
+
/**
|
92 |
+
* constructor - see top of this file for cache type and cache_options
|
93 |
+
*
|
94 |
+
* @param string $host
|
95 |
+
* @param string $database
|
96 |
+
* @param string $username
|
97 |
+
* @param string $password
|
98 |
+
* @param string $table
|
99 |
+
*
|
100 |
+
* @throws Exception
|
101 |
+
* @throws getid3_exception
|
102 |
+
*/
|
103 |
+
public function __construct($host, $database, $username, $password, $table='getid3_cache') {
|
104 |
+
|
105 |
+
// Check for mysqli support
|
106 |
+
if (!function_exists('mysqli_connect')) {
|
107 |
+
throw new Exception('PHP not compiled with mysqli support.');
|
108 |
+
}
|
109 |
+
|
110 |
+
// Connect to database
|
111 |
+
$this->mysqli = new mysqli($host, $username, $password);
|
112 |
+
if (!$this->mysqli) {
|
113 |
+
throw new Exception('mysqli_connect() failed - check permissions and spelling.');
|
114 |
+
}
|
115 |
+
|
116 |
+
// Select database
|
117 |
+
if (!$this->mysqli->select_db($database)) {
|
118 |
+
throw new Exception('Cannot use database '.$database);
|
119 |
+
}
|
120 |
+
|
121 |
+
// Set table
|
122 |
+
$this->table = $table;
|
123 |
+
|
124 |
+
// Create cache table if not exists
|
125 |
+
$this->create_table();
|
126 |
+
|
127 |
+
// Check version number and clear cache if changed
|
128 |
+
$version = '';
|
129 |
+
$SQLquery = 'SELECT `value`';
|
130 |
+
$SQLquery .= ' FROM `'.$this->mysqli->real_escape_string($this->table).'`';
|
131 |
+
$SQLquery .= ' WHERE (`filename` = \''.$this->mysqli->real_escape_string(getID3::VERSION).'\')';
|
132 |
+
$SQLquery .= ' AND (`filesize` = -1)';
|
133 |
+
$SQLquery .= ' AND (`filetime` = -1)';
|
134 |
+
$SQLquery .= ' AND (`analyzetime` = -1)';
|
135 |
+
if ($this->cursor = $this->mysqli->query($SQLquery)) {
|
136 |
+
list($version) = $this->cursor->fetch_array();
|
137 |
+
}
|
138 |
+
if ($version != getID3::VERSION) {
|
139 |
+
$this->clear_cache();
|
140 |
+
}
|
141 |
+
|
142 |
+
parent::__construct();
|
143 |
+
}
|
144 |
+
|
145 |
+
|
146 |
+
/**
|
147 |
+
* clear cache
|
148 |
+
*/
|
149 |
+
public function clear_cache() {
|
150 |
+
$this->mysqli->query('DELETE FROM `'.$this->mysqli->real_escape_string($this->table).'`');
|
151 |
+
$this->mysqli->query('INSERT INTO `'.$this->mysqli->real_escape_string($this->table).'` (`filename`, `filesize`, `filetime`, `analyzetime`, `value`) VALUES (\''.getID3::VERSION.'\', -1, -1, -1, \''.getID3::VERSION.'\')');
|
152 |
+
}
|
153 |
+
|
154 |
+
|
155 |
+
/**
|
156 |
+
* analyze file
|
157 |
+
*
|
158 |
+
* @param string $filename
|
159 |
+
* @param int $filesize
|
160 |
+
* @param string $original_filename
|
161 |
+
*
|
162 |
+
* @return mixed
|
163 |
+
*/
|
164 |
+
public function analyze($filename, $filesize=null, $original_filename='') {
|
165 |
+
|
166 |
+
$filetime = 0;
|
167 |
+
if (file_exists($filename)) {
|
168 |
+
|
169 |
+
// Short-hands
|
170 |
+
$filetime = filemtime($filename);
|
171 |
+
$filesize = filesize($filename);
|
172 |
+
|
173 |
+
// Lookup file
|
174 |
+
$SQLquery = 'SELECT `value`';
|
175 |
+
$SQLquery .= ' FROM `'.$this->mysqli->real_escape_string($this->table).'`';
|
176 |
+
$SQLquery .= ' WHERE (`filename` = \''.$this->mysqli->real_escape_string($filename).'\')';
|
177 |
+
$SQLquery .= ' AND (`filesize` = \''.$this->mysqli->real_escape_string($filesize).'\')';
|
178 |
+
$SQLquery .= ' AND (`filetime` = \''.$this->mysqli->real_escape_string($filetime).'\')';
|
179 |
+
$this->cursor = $this->mysqli->query($SQLquery);
|
180 |
+
if ($this->cursor->num_rows > 0) {
|
181 |
+
// Hit
|
182 |
+
list($result) = $this->cursor->fetch_array();
|
183 |
+
return unserialize(base64_decode($result));
|
184 |
+
}
|
185 |
+
}
|
186 |
+
|
187 |
+
// Miss
|
188 |
+
$analysis = parent::analyze($filename, $filesize, $original_filename);
|
189 |
+
|
190 |
+
// Save result
|
191 |
+
if (file_exists($filename)) {
|
192 |
+
$SQLquery = 'INSERT INTO `'.$this->mysqli->real_escape_string($this->table).'` (`filename`, `filesize`, `filetime`, `analyzetime`, `value`) VALUES (';
|
193 |
+
$SQLquery .= '\''.$this->mysqli->real_escape_string($filename).'\'';
|
194 |
+
$SQLquery .= ', \''.$this->mysqli->real_escape_string($filesize).'\'';
|
195 |
+
$SQLquery .= ', \''.$this->mysqli->real_escape_string($filetime).'\'';
|
196 |
+
$SQLquery .= ', \''.$this->mysqli->real_escape_string(time() ).'\'';
|
197 |
+
$SQLquery .= ', \''.$this->mysqli->real_escape_string(base64_encode(serialize($analysis))).'\')';
|
198 |
+
$this->cursor = $this->mysqli->query($SQLquery);
|
199 |
+
}
|
200 |
+
return $analysis;
|
201 |
+
}
|
202 |
+
|
203 |
+
|
204 |
+
/**
|
205 |
+
* (re)create mysqli table
|
206 |
+
*
|
207 |
+
* @param bool $drop
|
208 |
+
*/
|
209 |
+
private function create_table($drop=false) {
|
210 |
+
$SQLquery = 'CREATE TABLE IF NOT EXISTS `'.$this->mysqli->real_escape_string($this->table).'` (';
|
211 |
+
$SQLquery .= '`filename` VARCHAR(990) NOT NULL DEFAULT \'\'';
|
212 |
+
$SQLquery .= ', `filesize` INT(11) NOT NULL DEFAULT \'0\'';
|
213 |
+
$SQLquery .= ', `filetime` INT(11) NOT NULL DEFAULT \'0\'';
|
214 |
+
$SQLquery .= ', `analyzetime` INT(11) NOT NULL DEFAULT \'0\'';
|
215 |
+
$SQLquery .= ', `value` LONGTEXT NOT NULL';
|
216 |
+
$SQLquery .= ', PRIMARY KEY (`filename`, `filesize`, `filetime`))';
|
217 |
+
$this->cursor = $this->mysqli->query($SQLquery);
|
218 |
+
echo $this->mysqli->error;
|
219 |
+
}
|
220 |
+
}
|
lib/getid3/extension.cache.sqlite3.php
CHANGED
@@ -1,21 +1,27 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
-
/// getID3() by James Heinrich <info@getid3.org>
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
|
9 |
-
//
|
10 |
-
//
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
//
|
15 |
-
//
|
16 |
-
|
17 |
-
//
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
/**
|
20 |
* This is a caching extension for getID3(). It works the exact same
|
21 |
* way as the getID3 class, but return cached information much faster
|
@@ -89,14 +95,35 @@
|
|
89 |
*
|
90 |
*
|
91 |
*/
|
92 |
-
class getID3_cached_sqlite3 extends getID3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
|
94 |
/**
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
public function __construct($table='getid3_cache', $hide=false) {
|
|
|
|
|
|
|
|
|
|
|
100 |
$this->table = $table; // Set table
|
101 |
$file = dirname(__FILE__).'/'.basename(__FILE__, 'php').'sqlite';
|
102 |
if ($hide) {
|
@@ -106,7 +133,7 @@ class getID3_cached_sqlite3 extends getID3 {
|
|
106 |
$db = $this->db;
|
107 |
$this->create_table(); // Create cache table if not exists
|
108 |
$version = '';
|
109 |
-
$sql = $this->version_check;
|
110 |
$stmt = $db->prepare($sql);
|
111 |
$stmt->bindValue(':filename', getID3::VERSION, SQLITE3_TEXT);
|
112 |
$result = $stmt->execute();
|
@@ -114,39 +141,27 @@ class getID3_cached_sqlite3 extends getID3 {
|
|
114 |
if ($version != getID3::VERSION) { // Check version number and clear cache if changed
|
115 |
$this->clear_cache();
|
116 |
}
|
117 |
-
|
118 |
}
|
119 |
|
120 |
/**
|
121 |
-
|
122 |
-
|
123 |
public function __destruct() {
|
124 |
$db=$this->db;
|
125 |
$db->close();
|
126 |
}
|
127 |
|
128 |
/**
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
/**
|
135 |
-
* table to use for caching
|
136 |
-
* @var string $table
|
137 |
-
*/
|
138 |
-
private $table;
|
139 |
-
|
140 |
-
/**
|
141 |
-
* clear the cache
|
142 |
-
* @access private
|
143 |
-
* @return type
|
144 |
-
*/
|
145 |
private function clear_cache() {
|
146 |
$db = $this->db;
|
147 |
-
$sql = $this->delete_cache;
|
148 |
$db->exec($sql);
|
149 |
-
$sql = $this->set_version;
|
150 |
$stmt = $db->prepare($sql);
|
151 |
$stmt->bindValue(':filename', getID3::VERSION, SQLITE3_TEXT);
|
152 |
$stmt->bindValue(':dirname', getID3::VERSION, SQLITE3_TEXT);
|
@@ -155,72 +170,77 @@ class getID3_cached_sqlite3 extends getID3 {
|
|
155 |
}
|
156 |
|
157 |
/**
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
|
|
|
|
|
|
|
|
162 |
public function analyze($filename, $filesize=null, $original_filename='') {
|
163 |
if (!file_exists($filename)) {
|
164 |
return false;
|
165 |
}
|
166 |
// items to track for caching
|
167 |
$filetime = filemtime($filename);
|
168 |
-
$
|
169 |
// this will be saved for a quick directory lookup of analized files
|
170 |
// ... why do 50 seperate sql quries when you can do 1 for the same result
|
171 |
$dirname = dirname($filename);
|
172 |
// Lookup file
|
173 |
$db = $this->db;
|
174 |
-
$sql = $this->get_id3_data;
|
175 |
$stmt = $db->prepare($sql);
|
176 |
-
$stmt->bindValue(':filename', $filename,
|
177 |
-
$stmt->bindValue(':filesize', $
|
178 |
-
$stmt->bindValue(':filetime', $filetime,
|
179 |
$res = $stmt->execute();
|
180 |
list($result) = $res->fetchArray();
|
181 |
if (count($result) > 0 ) {
|
182 |
return unserialize(base64_decode($result));
|
183 |
}
|
184 |
// if it hasn't been analyzed before, then do it now
|
185 |
-
$analysis = parent::analyze($filename, $filesize
|
186 |
// Save result
|
187 |
-
$sql = $this->cache_file;
|
188 |
$stmt = $db->prepare($sql);
|
189 |
-
$stmt->bindValue(':filename', $filename,
|
190 |
-
$stmt->bindValue(':dirname',
|
191 |
-
$stmt->bindValue(':filesize', $
|
192 |
-
$stmt->bindValue(':filetime', $filetime,
|
193 |
-
$stmt->bindValue(':atime',
|
194 |
-
$stmt->bindValue(':val',
|
195 |
$res = $stmt->execute();
|
196 |
return $analysis;
|
197 |
}
|
198 |
|
199 |
/**
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
|
|
204 |
private function create_table() {
|
205 |
$db = $this->db;
|
206 |
-
$sql = $this->make_table;
|
207 |
return $db->exec($sql);
|
208 |
}
|
209 |
|
210 |
/**
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
public function get_cached_dir($dir) {
|
221 |
$db = $this->db;
|
222 |
$rows = array();
|
223 |
-
$sql = $this->get_cached_dir;
|
224 |
$stmt = $db->prepare($sql);
|
225 |
$stmt->bindValue(':dirname', $dir, SQLITE3_TEXT);
|
226 |
$res = $stmt->execute();
|
@@ -231,12 +251,15 @@ class getID3_cached_sqlite3 extends getID3 {
|
|
231 |
}
|
232 |
|
233 |
/**
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
|
|
|
|
|
|
240 |
case 'version_check':
|
241 |
return "SELECT val FROM $this->table WHERE filename = :filename AND filesize = '-1' AND filetime = '-1' AND analyzetime = '-1'";
|
242 |
break;
|
@@ -253,14 +276,28 @@ class getID3_cached_sqlite3 extends getID3 {
|
|
253 |
return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, :filesize, :filetime, :atime, :val)";
|
254 |
break;
|
255 |
case 'make_table':
|
256 |
-
//return "CREATE TABLE IF NOT EXISTS $this->table (filename VARCHAR(255) NOT NULL DEFAULT '', dirname VARCHAR(255) NOT NULL DEFAULT '', filesize INT(11) NOT NULL DEFAULT '0', filetime INT(11) NOT NULL DEFAULT '0', analyzetime INT(11) NOT NULL DEFAULT '0', val text not null, PRIMARY KEY (filename, filesize, filetime))";
|
257 |
return "CREATE TABLE IF NOT EXISTS $this->table (filename VARCHAR(255) DEFAULT '', dirname VARCHAR(255) DEFAULT '', filesize INT(11) DEFAULT '0', filetime INT(11) DEFAULT '0', analyzetime INT(11) DEFAULT '0', val text, PRIMARY KEY (filename, filesize, filetime))";
|
258 |
break;
|
259 |
case 'get_cached_dir':
|
260 |
return "SELECT val FROM $this->table WHERE dirname = :dirname";
|
261 |
break;
|
|
|
|
|
262 |
}
|
263 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
264 |
}
|
265 |
|
266 |
}
|
1 |
<?php
|
2 |
+
/////////////////////////////////////////////////////////////////
|
3 |
+
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
5 |
+
// or https://www.getid3.org //
|
6 |
+
// or http://getid3.sourceforge.net //
|
7 |
+
// //
|
8 |
+
// extension.cache.mysqli.php - part of getID3() //
|
9 |
+
// Please see readme.txt for more information //
|
10 |
+
// //
|
11 |
+
/////////////////////////////////////////////////////////////////
|
12 |
+
// //
|
13 |
+
// extension.cache.sqlite3.php - part of getID3() //
|
14 |
+
// Please see readme.txt for more information //
|
15 |
+
// //
|
16 |
+
/////////////////////////////////////////////////////////////////
|
17 |
+
/// //
|
18 |
+
// MySQL extension written by Allan Hansen <ahØartemis*dk> //
|
19 |
+
// Table name mod by Carlo Capocasa <calroØcarlocapocasa*com> //
|
20 |
+
// MySQL extension was reworked for SQLite3 by //
|
21 |
+
// Karl G. Holz <newaeonØmac*com> //
|
22 |
+
// ///
|
23 |
+
/////////////////////////////////////////////////////////////////
|
24 |
+
|
25 |
/**
|
26 |
* This is a caching extension for getID3(). It works the exact same
|
27 |
* way as the getID3 class, but return cached information much faster
|
95 |
*
|
96 |
*
|
97 |
*/
|
98 |
+
class getID3_cached_sqlite3 extends getID3
|
99 |
+
{
|
100 |
+
/**
|
101 |
+
* hold the sqlite db
|
102 |
+
*
|
103 |
+
* @var SQLite3 Resource
|
104 |
+
*/
|
105 |
+
private $db;
|
106 |
|
107 |
/**
|
108 |
+
* table to use for caching
|
109 |
+
*
|
110 |
+
* @var string $table
|
111 |
+
*/
|
112 |
+
private $table;
|
113 |
+
|
114 |
+
/**
|
115 |
+
* @param string $table holds name of sqlite table
|
116 |
+
* @param boolean $hide
|
117 |
+
*
|
118 |
+
* @throws getid3_exception
|
119 |
+
* @throws Exception
|
120 |
+
*/
|
121 |
public function __construct($table='getid3_cache', $hide=false) {
|
122 |
+
// Check for SQLite3 support
|
123 |
+
if (!function_exists('sqlite_open')) {
|
124 |
+
throw new Exception('PHP not compiled with SQLite3 support.');
|
125 |
+
}
|
126 |
+
|
127 |
$this->table = $table; // Set table
|
128 |
$file = dirname(__FILE__).'/'.basename(__FILE__, 'php').'sqlite';
|
129 |
if ($hide) {
|
133 |
$db = $this->db;
|
134 |
$this->create_table(); // Create cache table if not exists
|
135 |
$version = '';
|
136 |
+
$sql = $this->getQuery('version_check');
|
137 |
$stmt = $db->prepare($sql);
|
138 |
$stmt->bindValue(':filename', getID3::VERSION, SQLITE3_TEXT);
|
139 |
$result = $stmt->execute();
|
141 |
if ($version != getID3::VERSION) { // Check version number and clear cache if changed
|
142 |
$this->clear_cache();
|
143 |
}
|
144 |
+
parent::__construct();
|
145 |
}
|
146 |
|
147 |
/**
|
148 |
+
* close the database connection
|
149 |
+
*/
|
150 |
public function __destruct() {
|
151 |
$db=$this->db;
|
152 |
$db->close();
|
153 |
}
|
154 |
|
155 |
/**
|
156 |
+
* clear the cache
|
157 |
+
*
|
158 |
+
* @return SQLite3Result
|
159 |
+
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
160 |
private function clear_cache() {
|
161 |
$db = $this->db;
|
162 |
+
$sql = $this->getQuery('delete_cache');
|
163 |
$db->exec($sql);
|
164 |
+
$sql = $this->getQuery('set_version');
|
165 |
$stmt = $db->prepare($sql);
|
166 |
$stmt->bindValue(':filename', getID3::VERSION, SQLITE3_TEXT);
|
167 |
$stmt->bindValue(':dirname', getID3::VERSION, SQLITE3_TEXT);
|
170 |
}
|
171 |
|
172 |
/**
|
173 |
+
* analyze file and cache them, if cached pull from the db
|
174 |
+
*
|
175 |
+
* @param string $filename
|
176 |
+
* @param integer $filesize
|
177 |
+
* @param string $original_filename
|
178 |
+
*
|
179 |
+
* @return mixed|false
|
180 |
+
*/
|
181 |
public function analyze($filename, $filesize=null, $original_filename='') {
|
182 |
if (!file_exists($filename)) {
|
183 |
return false;
|
184 |
}
|
185 |
// items to track for caching
|
186 |
$filetime = filemtime($filename);
|
187 |
+
$filesize_real = filesize($filename);
|
188 |
// this will be saved for a quick directory lookup of analized files
|
189 |
// ... why do 50 seperate sql quries when you can do 1 for the same result
|
190 |
$dirname = dirname($filename);
|
191 |
// Lookup file
|
192 |
$db = $this->db;
|
193 |
+
$sql = $this->getQuery('get_id3_data');
|
194 |
$stmt = $db->prepare($sql);
|
195 |
+
$stmt->bindValue(':filename', $filename, SQLITE3_TEXT);
|
196 |
+
$stmt->bindValue(':filesize', $filesize_real, SQLITE3_INTEGER);
|
197 |
+
$stmt->bindValue(':filetime', $filetime, SQLITE3_INTEGER);
|
198 |
$res = $stmt->execute();
|
199 |
list($result) = $res->fetchArray();
|
200 |
if (count($result) > 0 ) {
|
201 |
return unserialize(base64_decode($result));
|
202 |
}
|
203 |
// if it hasn't been analyzed before, then do it now
|
204 |
+
$analysis = parent::analyze($filename, $filesize, $original_filename);
|
205 |
// Save result
|
206 |
+
$sql = $this->getQuery('cache_file');
|
207 |
$stmt = $db->prepare($sql);
|
208 |
+
$stmt->bindValue(':filename', $filename, SQLITE3_TEXT);
|
209 |
+
$stmt->bindValue(':dirname', $dirname, SQLITE3_TEXT);
|
210 |
+
$stmt->bindValue(':filesize', $filesize_real, SQLITE3_INTEGER);
|
211 |
+
$stmt->bindValue(':filetime', $filetime, SQLITE3_INTEGER);
|
212 |
+
$stmt->bindValue(':atime', time(), SQLITE3_INTEGER);
|
213 |
+
$stmt->bindValue(':val', base64_encode(serialize($analysis)), SQLITE3_TEXT);
|
214 |
$res = $stmt->execute();
|
215 |
return $analysis;
|
216 |
}
|
217 |
|
218 |
/**
|
219 |
+
* create data base table
|
220 |
+
* this is almost the same as MySQL, with the exception of the dirname being added
|
221 |
+
*
|
222 |
+
* @return bool
|
223 |
+
*/
|
224 |
private function create_table() {
|
225 |
$db = $this->db;
|
226 |
+
$sql = $this->getQuery('make_table');
|
227 |
return $db->exec($sql);
|
228 |
}
|
229 |
|
230 |
/**
|
231 |
+
* get cached directory
|
232 |
+
*
|
233 |
+
* This function is not in the MySQL extention, it's ment to speed up requesting multiple files
|
234 |
+
* which is ideal for podcasting, playlists, etc.
|
235 |
+
*
|
236 |
+
* @param string $dir directory to search the cache database for
|
237 |
+
*
|
238 |
+
* @return array return an array of matching id3 data
|
239 |
+
*/
|
240 |
public function get_cached_dir($dir) {
|
241 |
$db = $this->db;
|
242 |
$rows = array();
|
243 |
+
$sql = $this->getQuery('get_cached_dir');
|
244 |
$stmt = $db->prepare($sql);
|
245 |
$stmt->bindValue(':dirname', $dir, SQLITE3_TEXT);
|
246 |
$res = $stmt->execute();
|
251 |
}
|
252 |
|
253 |
/**
|
254 |
+
* returns NULL if query is not found
|
255 |
+
*
|
256 |
+
* @param string $name
|
257 |
+
*
|
258 |
+
* @return null|string
|
259 |
+
*/
|
260 |
+
public function getQuery($name)
|
261 |
+
{
|
262 |
+
switch ($name) {
|
263 |
case 'version_check':
|
264 |
return "SELECT val FROM $this->table WHERE filename = :filename AND filesize = '-1' AND filetime = '-1' AND analyzetime = '-1'";
|
265 |
break;
|
276 |
return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, :filesize, :filetime, :atime, :val)";
|
277 |
break;
|
278 |
case 'make_table':
|
|
|
279 |
return "CREATE TABLE IF NOT EXISTS $this->table (filename VARCHAR(255) DEFAULT '', dirname VARCHAR(255) DEFAULT '', filesize INT(11) DEFAULT '0', filetime INT(11) DEFAULT '0', analyzetime INT(11) DEFAULT '0', val text, PRIMARY KEY (filename, filesize, filetime))";
|
280 |
break;
|
281 |
case 'get_cached_dir':
|
282 |
return "SELECT val FROM $this->table WHERE dirname = :dirname";
|
283 |
break;
|
284 |
+
default:
|
285 |
+
return null;
|
286 |
}
|
287 |
+
}
|
288 |
+
|
289 |
+
/**
|
290 |
+
* use the magical __get() for sql queries
|
291 |
+
*
|
292 |
+
* access as easy as $this->{case name}, returns NULL if query is not found
|
293 |
+
*
|
294 |
+
* @param string $name
|
295 |
+
*
|
296 |
+
* @return string
|
297 |
+
* @deprecated use getQuery() instead
|
298 |
+
*/
|
299 |
+
public function __get($name) {
|
300 |
+
return $this->getQuery($name);
|
301 |
}
|
302 |
|
303 |
}
|
lib/getid3/getid3.lib.php
CHANGED
@@ -1,20 +1,27 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
/////////////////////////////////////////////////////////////////
|
8 |
// //
|
9 |
// getid3.lib.php - part of getID3() //
|
10 |
-
//
|
11 |
// ///
|
12 |
/////////////////////////////////////////////////////////////////
|
13 |
|
14 |
|
15 |
class getid3_lib
|
16 |
{
|
17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
public static function PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8') {
|
19 |
$returnstring = '';
|
20 |
for ($i = 0; $i < strlen($string); $i++) {
|
@@ -36,9 +43,14 @@ class getid3_lib
|
|
36 |
return $returnstring;
|
37 |
}
|
38 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
public static function trunc($floatnumber) {
|
40 |
-
// truncates a floating-point number at the decimal point
|
41 |
-
// returns int (if possible, otherwise float)
|
42 |
if ($floatnumber >= 1) {
|
43 |
$truncatednumber = floor($floatnumber);
|
44 |
} elseif ($floatnumber <= -1) {
|
@@ -52,7 +64,12 @@ class getid3_lib
|
|
52 |
return $truncatednumber;
|
53 |
}
|
54 |
|
55 |
-
|
|
|
|
|
|
|
|
|
|
|
56 |
public static function safe_inc(&$variable, $increment=1) {
|
57 |
if (isset($variable)) {
|
58 |
$variable += $increment;
|
@@ -62,6 +79,11 @@ class getid3_lib
|
|
62 |
return true;
|
63 |
}
|
64 |
|
|
|
|
|
|
|
|
|
|
|
65 |
public static function CastAsInt($floatnum) {
|
66 |
// convert to float if not already
|
67 |
$floatnum = (float) $floatnum;
|
@@ -77,6 +99,11 @@ class getid3_lib
|
|
77 |
return $floatnum;
|
78 |
}
|
79 |
|
|
|
|
|
|
|
|
|
|
|
80 |
public static function intValueSupported($num) {
|
81 |
// check if integers are 64-bit
|
82 |
static $hasINT64 = null;
|
@@ -93,21 +120,36 @@ class getid3_lib
|
|
93 |
return false;
|
94 |
}
|
95 |
|
|
|
|
|
|
|
|
|
|
|
96 |
public static function DecimalizeFraction($fraction) {
|
97 |
list($numerator, $denominator) = explode('/', $fraction);
|
98 |
return $numerator / ($denominator ? $denominator : 1);
|
99 |
}
|
100 |
|
101 |
-
|
|
|
|
|
|
|
|
|
102 |
public static function DecimalBinary2Float($binarynumerator) {
|
103 |
$numerator = self::Bin2Dec($binarynumerator);
|
104 |
$denominator = self::Bin2Dec('1'.str_repeat('0', strlen($binarynumerator)));
|
105 |
return ($numerator / $denominator);
|
106 |
}
|
107 |
|
108 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
public static function NormalizeBinaryPoint($binarypointnumber, $maxbits=52) {
|
110 |
-
// http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
|
111 |
if (strpos($binarypointnumber, '.') === false) {
|
112 |
$binarypointnumber = '0.'.$binarypointnumber;
|
113 |
} elseif ($binarypointnumber{0} == '.') {
|
@@ -129,9 +171,14 @@ class getid3_lib
|
|
129 |
return array('normalized'=>$binarypointnumber, 'exponent'=>(int) $exponent);
|
130 |
}
|
131 |
|
132 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
133 |
public static function Float2BinaryDecimal($floatvalue) {
|
134 |
-
// http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
|
135 |
$maxbits = 128; // to how many bits of precision should the calculations be taken?
|
136 |
$intpart = self::trunc($floatvalue);
|
137 |
$floatpart = abs($floatvalue - $intpart);
|
@@ -145,9 +192,17 @@ class getid3_lib
|
|
145 |
return $binarypointnumber;
|
146 |
}
|
147 |
|
148 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
149 |
public static function Float2String($floatvalue, $bits) {
|
150 |
-
|
|
|
151 |
switch ($bits) {
|
152 |
case 32:
|
153 |
$exponentbits = 8;
|
@@ -176,22 +231,34 @@ class getid3_lib
|
|
176 |
return self::BigEndian2String(self::Bin2Dec($signbit.$exponentbitstring.$fractionbitstring), $bits % 8, false);
|
177 |
}
|
178 |
|
179 |
-
|
|
|
|
|
|
|
|
|
180 |
public static function LittleEndian2Float($byteword) {
|
181 |
return self::BigEndian2Float(strrev($byteword));
|
182 |
}
|
183 |
|
184 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
185 |
public static function BigEndian2Float($byteword) {
|
186 |
-
// ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic
|
187 |
-
// http://www.psc.edu/general/software/packages/ieee/ieee.html
|
188 |
-
// http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html
|
189 |
-
|
190 |
$bitword = self::BigEndian2Bin($byteword);
|
191 |
if (!$bitword) {
|
192 |
return 0;
|
193 |
}
|
194 |
$signbit = $bitword{0};
|
|
|
|
|
|
|
195 |
|
196 |
switch (strlen($byteword) * 8) {
|
197 |
case 32:
|
@@ -259,7 +326,14 @@ class getid3_lib
|
|
259 |
return (float) $floatvalue;
|
260 |
}
|
261 |
|
262 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
263 |
public static function BigEndian2Int($byteword, $synchsafe=false, $signed=false) {
|
264 |
$intvalue = 0;
|
265 |
$bytewordlen = strlen($byteword);
|
@@ -288,12 +362,30 @@ class getid3_lib
|
|
288 |
return self::CastAsInt($intvalue);
|
289 |
}
|
290 |
|
291 |
-
|
|
|
|
|
|
|
|
|
|
|
292 |
public static function LittleEndian2Int($byteword, $signed=false) {
|
293 |
return self::BigEndian2Int(strrev($byteword), false, $signed);
|
294 |
}
|
295 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
296 |
|
|
|
|
|
|
|
|
|
|
|
297 |
public static function BigEndian2Bin($byteword) {
|
298 |
$binvalue = '';
|
299 |
$bytewordlen = strlen($byteword);
|
@@ -303,7 +395,15 @@ class getid3_lib
|
|
303 |
return $binvalue;
|
304 |
}
|
305 |
|
306 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
307 |
public static function BigEndian2String($number, $minbytes=1, $synchsafe=false, $signed=false) {
|
308 |
if ($number < 0) {
|
309 |
throw new Exception('ERROR: self::BigEndian2String() does not support negative numbers');
|
@@ -324,7 +424,11 @@ class getid3_lib
|
|
324 |
return str_pad($intstring, $minbytes, "\x00", STR_PAD_LEFT);
|
325 |
}
|
326 |
|
327 |
-
|
|
|
|
|
|
|
|
|
328 |
public static function Dec2Bin($number) {
|
329 |
while ($number >= 256) {
|
330 |
$bytes[] = (($number / 256) - (floor($number / 256))) * 256;
|
@@ -338,7 +442,12 @@ class getid3_lib
|
|
338 |
return $binstring;
|
339 |
}
|
340 |
|
341 |
-
|
|
|
|
|
|
|
|
|
|
|
342 |
public static function Bin2Dec($binstring, $signed=false) {
|
343 |
$signmult = 1;
|
344 |
if ($signed) {
|
@@ -354,7 +463,11 @@ class getid3_lib
|
|
354 |
return self::CastAsInt($decvalue * $signmult);
|
355 |
}
|
356 |
|
357 |
-
|
|
|
|
|
|
|
|
|
358 |
public static function Bin2String($binstring) {
|
359 |
// return 'hi' for input of '0110100001101001'
|
360 |
$string = '';
|
@@ -365,7 +478,13 @@ class getid3_lib
|
|
365 |
return $string;
|
366 |
}
|
367 |
|
368 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
369 |
public static function LittleEndian2String($number, $minbytes=1, $synchsafe=false) {
|
370 |
$intstring = '';
|
371 |
while ($number > 0) {
|
@@ -380,7 +499,12 @@ class getid3_lib
|
|
380 |
return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT);
|
381 |
}
|
382 |
|
383 |
-
|
|
|
|
|
|
|
|
|
|
|
384 |
public static function array_merge_clobber($array1, $array2) {
|
385 |
// written by kcØhireability*com
|
386 |
// taken from http://www.php.net/manual/en/function.array-merge-recursive.php
|
@@ -398,7 +522,12 @@ class getid3_lib
|
|
398 |
return $newarray;
|
399 |
}
|
400 |
|
401 |
-
|
|
|
|
|
|
|
|
|
|
|
402 |
public static function array_merge_noclobber($array1, $array2) {
|
403 |
if (!is_array($array1) || !is_array($array2)) {
|
404 |
return false;
|
@@ -414,6 +543,12 @@ class getid3_lib
|
|
414 |
return $newarray;
|
415 |
}
|
416 |
|
|
|
|
|
|
|
|
|
|
|
|
|
417 |
public static function flipped_array_merge_noclobber($array1, $array2) {
|
418 |
if (!is_array($array1) || !is_array($array2)) {
|
419 |
return false;
|
@@ -428,7 +563,11 @@ class getid3_lib
|
|
428 |
return array_flip($newarray);
|
429 |
}
|
430 |
|
431 |
-
|
|
|
|
|
|
|
|
|
432 |
public static function ksort_recursive(&$theArray) {
|
433 |
ksort($theArray);
|
434 |
foreach ($theArray as $key => $value) {
|
@@ -439,6 +578,12 @@ class getid3_lib
|
|
439 |
return true;
|
440 |
}
|
441 |
|
|
|
|
|
|
|
|
|
|
|
|
|
442 |
public static function fileextension($filename, $numextensions=1) {
|
443 |
if (strstr($filename, '.')) {
|
444 |
$reversedfilename = strrev($filename);
|
@@ -454,7 +599,11 @@ class getid3_lib
|
|
454 |
return '';
|
455 |
}
|
456 |
|
457 |
-
|
|
|
|
|
|
|
|
|
458 |
public static function PlaytimeString($seconds) {
|
459 |
$sign = (($seconds < 0) ? '-' : '');
|
460 |
$seconds = round(abs($seconds));
|
@@ -464,30 +613,53 @@ class getid3_lib
|
|
464 |
return $sign.($H ? $H.':' : '').($H ? str_pad($M, 2, '0', STR_PAD_LEFT) : intval($M)).':'.str_pad($S, 2, 0, STR_PAD_LEFT);
|
465 |
}
|
466 |
|
467 |
-
|
|
|
|
|
|
|
|
|
468 |
public static function DateMac2Unix($macdate) {
|
469 |
// Macintosh timestamp: seconds since 00:00h January 1, 1904
|
470 |
// UNIX timestamp: seconds since 00:00h January 1, 1970
|
471 |
return self::CastAsInt($macdate - 2082844800);
|
472 |
}
|
473 |
|
474 |
-
|
|
|
|
|
|
|
|
|
475 |
public static function FixedPoint8_8($rawdata) {
|
476 |
return self::BigEndian2Int(substr($rawdata, 0, 1)) + (float) (self::BigEndian2Int(substr($rawdata, 1, 1)) / pow(2, 8));
|
477 |
}
|
478 |
|
479 |
-
|
|
|
|
|
|
|
|
|
480 |
public static function FixedPoint16_16($rawdata) {
|
481 |
return self::BigEndian2Int(substr($rawdata, 0, 2)) + (float) (self::BigEndian2Int(substr($rawdata, 2, 2)) / pow(2, 16));
|
482 |
}
|
483 |
|
484 |
-
|
|
|
|
|
|
|
|
|
485 |
public static function FixedPoint2_30($rawdata) {
|
486 |
$binarystring = self::BigEndian2Bin($rawdata);
|
487 |
return self::Bin2Dec(substr($binarystring, 0, 2)) + (float) (self::Bin2Dec(substr($binarystring, 2, 30)) / pow(2, 30));
|
488 |
}
|
489 |
|
490 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
491 |
public static function CreateDeepArray($ArrayPath, $Separator, $Value) {
|
492 |
// assigns $Value to a nested array path:
|
493 |
// $foo = self::CreateDeepArray('/path/to/my', '/', 'file.txt')
|
@@ -504,6 +676,12 @@ class getid3_lib
|
|
504 |
return $ReturnedArray;
|
505 |
}
|
506 |
|
|
|
|
|
|
|
|
|
|
|
|
|
507 |
public static function array_max($arraydata, $returnkey=false) {
|
508 |
$maxvalue = false;
|
509 |
$maxkey = false;
|
@@ -518,6 +696,12 @@ class getid3_lib
|
|
518 |
return ($returnkey ? $maxkey : $maxvalue);
|
519 |
}
|
520 |
|
|
|
|
|
|
|
|
|
|
|
|
|
521 |
public static function array_min($arraydata, $returnkey=false) {
|
522 |
$minvalue = false;
|
523 |
$minkey = false;
|
@@ -532,6 +716,11 @@ class getid3_lib
|
|
532 |
return ($returnkey ? $minkey : $minvalue);
|
533 |
}
|
534 |
|
|
|
|
|
|
|
|
|
|
|
535 |
public static function XML2array($XMLstring) {
|
536 |
if (function_exists('simplexml_load_string') && function_exists('libxml_disable_entity_loader')) {
|
537 |
// http://websec.io/2012/08/27/Preventing-XEE-in-PHP.html
|
@@ -545,22 +734,42 @@ class getid3_lib
|
|
545 |
return false;
|
546 |
}
|
547 |
|
|
|
|
|
|
|
|
|
|
|
548 |
public static function SimpleXMLelement2array($XMLobject) {
|
549 |
if (!is_object($XMLobject) && !is_array($XMLobject)) {
|
550 |
return $XMLobject;
|
551 |
}
|
552 |
-
$XMLarray =
|
553 |
foreach ($XMLarray as $key => $value) {
|
554 |
$XMLarray[$key] = self::SimpleXMLelement2array($value);
|
555 |
}
|
556 |
return $XMLarray;
|
557 |
}
|
558 |
|
559 |
-
|
560 |
-
|
561 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
562 |
public static function hash_data($file, $offset, $end, $algorithm) {
|
563 |
static $tempdir = '';
|
|
|
|
|
|
|
|
|
564 |
if (!self::intValueSupported($end)) {
|
565 |
return false;
|
566 |
}
|
@@ -645,6 +854,15 @@ class getid3_lib
|
|
645 |
return $result;
|
646 |
}
|
647 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
648 |
public static function CopyFileParts($filename_source, $filename_dest, $offset, $length) {
|
649 |
if (!self::intValueSupported($offset + $length)) {
|
650 |
throw new Exception('cannot copy file portion, it extends beyond the '.round(PHP_INT_MAX / 1073741824).'GB limit');
|
@@ -657,21 +875,25 @@ class getid3_lib
|
|
657 |
$byteswritten = fwrite($fp_dest, $buffer, $byteslefttowrite);
|
658 |
$byteslefttowrite -= $byteswritten;
|
659 |
}
|
|
|
660 |
return true;
|
661 |
} else {
|
|
|
662 |
throw new Exception('failed to seek to offset '.$offset.' in '.$filename_source);
|
663 |
}
|
664 |
-
fclose($fp_dest);
|
665 |
} else {
|
666 |
throw new Exception('failed to create file for writing '.$filename_dest);
|
667 |
}
|
668 |
-
fclose($fp_src);
|
669 |
} else {
|
670 |
throw new Exception('failed to open file for reading '.$filename_source);
|
671 |
}
|
672 |
-
return false;
|
673 |
}
|
674 |
|
|
|
|
|
|
|
|
|
|
|
675 |
public static function iconv_fallback_int_utf8($charval) {
|
676 |
if ($charval < 128) {
|
677 |
// 0bbbbbbb
|
@@ -695,7 +917,14 @@ class getid3_lib
|
|
695 |
return $newcharstring;
|
696 |
}
|
697 |
|
698 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
699 |
public static function iconv_fallback_iso88591_utf8($string, $bom=false) {
|
700 |
if (function_exists('utf8_encode')) {
|
701 |
return utf8_encode($string);
|
@@ -712,7 +941,14 @@ class getid3_lib
|
|
712 |
return $newcharstring;
|
713 |
}
|
714 |
|
715 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
716 |
public static function iconv_fallback_iso88591_utf16be($string, $bom=false) {
|
717 |
$newcharstring = '';
|
718 |
if ($bom) {
|
@@ -724,7 +960,14 @@ class getid3_lib
|
|
724 |
return $newcharstring;
|
725 |
}
|
726 |
|
727 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
728 |
public static function iconv_fallback_iso88591_utf16le($string, $bom=false) {
|
729 |
$newcharstring = '';
|
730 |
if ($bom) {
|
@@ -736,12 +979,24 @@ class getid3_lib
|
|
736 |
return $newcharstring;
|
737 |
}
|
738 |
|
739 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
740 |
public static function iconv_fallback_iso88591_utf16($string) {
|
741 |
return self::iconv_fallback_iso88591_utf16le($string, true);
|
742 |
}
|
743 |
|
744 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
745 |
public static function iconv_fallback_utf8_iso88591($string) {
|
746 |
if (function_exists('utf8_decode')) {
|
747 |
return utf8_decode($string);
|
@@ -785,7 +1040,14 @@ class getid3_lib
|
|
785 |
return $newcharstring;
|
786 |
}
|
787 |
|
788 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
789 |
public static function iconv_fallback_utf8_utf16be($string, $bom=false) {
|
790 |
$newcharstring = '';
|
791 |
if ($bom) {
|
@@ -828,7 +1090,14 @@ class getid3_lib
|
|
828 |
return $newcharstring;
|
829 |
}
|
830 |
|
831 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
832 |
public static function iconv_fallback_utf8_utf16le($string, $bom=false) {
|
833 |
$newcharstring = '';
|
834 |
if ($bom) {
|
@@ -871,12 +1140,24 @@ class getid3_lib
|
|
871 |
return $newcharstring;
|
872 |
}
|
873 |
|
874 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
875 |
public static function iconv_fallback_utf8_utf16($string) {
|
876 |
return self::iconv_fallback_utf8_utf16le($string, true);
|
877 |
}
|
878 |
|
879 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
880 |
public static function iconv_fallback_utf16be_utf8($string) {
|
881 |
if (substr($string, 0, 2) == "\xFE\xFF") {
|
882 |
// strip BOM
|
@@ -890,7 +1171,13 @@ class getid3_lib
|
|
890 |
return $newcharstring;
|
891 |
}
|
892 |
|
893 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
894 |
public static function iconv_fallback_utf16le_utf8($string) {
|
895 |
if (substr($string, 0, 2) == "\xFF\xFE") {
|
896 |
// strip BOM
|
@@ -904,7 +1191,13 @@ class getid3_lib
|
|
904 |
return $newcharstring;
|
905 |
}
|
906 |
|
907 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
908 |
public static function iconv_fallback_utf16be_iso88591($string) {
|
909 |
if (substr($string, 0, 2) == "\xFE\xFF") {
|
910 |
// strip BOM
|
@@ -918,7 +1211,13 @@ class getid3_lib
|
|
918 |
return $newcharstring;
|
919 |
}
|
920 |
|
921 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
922 |
public static function iconv_fallback_utf16le_iso88591($string) {
|
923 |
if (substr($string, 0, 2) == "\xFF\xFE") {
|
924 |
// strip BOM
|
@@ -932,7 +1231,13 @@ class getid3_lib
|
|
932 |
return $newcharstring;
|
933 |
}
|
934 |
|
935 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
936 |
public static function iconv_fallback_utf16_iso88591($string) {
|
937 |
$bom = substr($string, 0, 2);
|
938 |
if ($bom == "\xFE\xFF") {
|
@@ -943,7 +1248,13 @@ class getid3_lib
|
|
943 |
return $string;
|
944 |
}
|
945 |
|
946 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
947 |
public static function iconv_fallback_utf16_utf8($string) {
|
948 |
$bom = substr($string, 0, 2);
|
949 |
if ($bom == "\xFE\xFF") {
|
@@ -954,14 +1265,34 @@ class getid3_lib
|
|
954 |
return $string;
|
955 |
}
|
956 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
957 |
public static function iconv_fallback($in_charset, $out_charset, $string) {
|
958 |
|
959 |
if ($in_charset == $out_charset) {
|
960 |
return $string;
|
961 |
}
|
962 |
|
963 |
-
//
|
964 |
-
if (function_exists('
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
965 |
if ($converted_string = @iconv($in_charset, $out_charset.'//TRANSLIT', $string)) {
|
966 |
switch ($out_charset) {
|
967 |
case 'ISO-8859-1':
|
@@ -977,7 +1308,7 @@ class getid3_lib
|
|
977 |
}
|
978 |
|
979 |
|
980 |
-
// iconv()
|
981 |
static $ConversionFunctionList = array();
|
982 |
if (empty($ConversionFunctionList)) {
|
983 |
$ConversionFunctionList['ISO-8859-1']['UTF-8'] = 'iconv_fallback_iso88591_utf8';
|
@@ -999,9 +1330,15 @@ class getid3_lib
|
|
999 |
$ConversionFunction = $ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)];
|
1000 |
return self::$ConversionFunction($string);
|
1001 |
}
|
1002 |
-
throw new Exception('PHP does not
|
1003 |
}
|
1004 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1005 |
public static function recursiveMultiByteCharString2HTML($data, $charset='ISO-8859-1') {
|
1006 |
if (is_string($data)) {
|
1007 |
return self::MultiByteCharString2HTML($data, $charset);
|
@@ -1016,42 +1353,48 @@ class getid3_lib
|
|
1016 |
return $data;
|
1017 |
}
|
1018 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1019 |
public static function MultiByteCharString2HTML($string, $charset='ISO-8859-1') {
|
1020 |
$string = (string) $string; // in case trying to pass a numeric (float, int) string, would otherwise return an empty string
|
1021 |
$HTMLstring = '';
|
1022 |
|
1023 |
-
switch ($charset) {
|
1024 |
case '1251':
|
1025 |
case '1252':
|
1026 |
case '866':
|
1027 |
case '932':
|
1028 |
case '936':
|
1029 |
case '950':
|
1030 |
-
case '
|
1031 |
-
case '
|
1032 |
case 'cp1251':
|
1033 |
case 'cp1252':
|
1034 |
case 'cp866':
|
1035 |
-
case '
|
1036 |
-
case '
|
1037 |
-
case '
|
1038 |
case 'ibm866':
|
1039 |
-
case '
|
1040 |
-
case '
|
1041 |
-
case '
|
1042 |
-
case '
|
1043 |
-
case '
|
1044 |
case 'koi8-ru':
|
1045 |
case 'koi8r':
|
1046 |
-
case '
|
1047 |
-
case '
|
1048 |
case 'win-1251':
|
1049 |
-
case '
|
1050 |
-
case '
|
1051 |
$HTMLstring = htmlentities($string, ENT_COMPAT, $charset);
|
1052 |
break;
|
1053 |
|
1054 |
-
case '
|
1055 |
$strlen = strlen($string);
|
1056 |
for ($i = 0; $i < $strlen; $i++) {
|
1057 |
$char_ord_val = ord($string{$i});
|
@@ -1079,7 +1422,7 @@ class getid3_lib
|
|
1079 |
}
|
1080 |
break;
|
1081 |
|
1082 |
-
case '
|
1083 |
for ($i = 0; $i < strlen($string); $i += 2) {
|
1084 |
$charval = self::LittleEndian2Int(substr($string, $i, 2));
|
1085 |
if (($charval >= 32) && ($charval <= 127)) {
|
@@ -1090,7 +1433,7 @@ class getid3_lib
|
|
1090 |
}
|
1091 |
break;
|
1092 |
|
1093 |
-
case '
|
1094 |
for ($i = 0; $i < strlen($string); $i += 2) {
|
1095 |
$charval = self::BigEndian2Int(substr($string, $i, 2));
|
1096 |
if (($charval >= 32) && ($charval <= 127)) {
|
@@ -1108,8 +1451,11 @@ class getid3_lib
|
|
1108 |
return $HTMLstring;
|
1109 |
}
|
1110 |
|
1111 |
-
|
1112 |
-
|
|
|
|
|
|
|
1113 |
public static function RGADnameLookup($namecode) {
|
1114 |
static $RGADname = array();
|
1115 |
if (empty($RGADname)) {
|
@@ -1121,7 +1467,11 @@ class getid3_lib
|
|
1121 |
return (isset($RGADname[$namecode]) ? $RGADname[$namecode] : '');
|
1122 |
}
|
1123 |
|
1124 |
-
|
|
|
|
|
|
|
|
|
1125 |
public static function RGADoriginatorLookup($originatorcode) {
|
1126 |
static $RGADoriginator = array();
|
1127 |
if (empty($RGADoriginator)) {
|
@@ -1134,16 +1484,27 @@ class getid3_lib
|
|
1134 |
return (isset($RGADoriginator[$originatorcode]) ? $RGADoriginator[$originatorcode] : '');
|
1135 |
}
|
1136 |
|
1137 |
-
|
|
|
|
|
|
|
|
|
|
|
1138 |
public static function RGADadjustmentLookup($rawadjustment, $signbit) {
|
1139 |
-
$adjustment = $rawadjustment / 10;
|
1140 |
if ($signbit == 1) {
|
1141 |
$adjustment *= -1;
|
1142 |
}
|
1143 |
-
return
|
1144 |
}
|
1145 |
|
1146 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
1147 |
public static function RGADgainString($namecode, $originatorcode, $replaygain) {
|
1148 |
if ($replaygain < 0) {
|
1149 |
$signbit = '1';
|
@@ -1159,19 +1520,37 @@ class getid3_lib
|
|
1159 |
return $gainstring;
|
1160 |
}
|
1161 |
|
|
|
|
|
|
|
|
|
|
|
1162 |
public static function RGADamplitude2dB($amplitude) {
|
1163 |
return 20 * log10($amplitude);
|
1164 |
}
|
1165 |
|
1166 |
-
|
|
|
|
|
|
|
|
|
|
|
1167 |
public static function GetDataImageSize($imgData, &$imageinfo=array()) {
|
1168 |
static $tempdir = '';
|
1169 |
if (empty($tempdir)) {
|
|
|
|
|
|
|
|
|
1170 |
// yes this is ugly, feel free to suggest a better way
|
1171 |
-
|
1172 |
-
|
1173 |
-
|
1174 |
-
|
|
|
|
|
|
|
|
|
1175 |
}
|
1176 |
$GetDataImageSize = false;
|
1177 |
if ($tempfilename = tempnam($tempdir, 'gI3')) {
|
@@ -1190,32 +1569,21 @@ class getid3_lib
|
|
1190 |
return $GetDataImageSize;
|
1191 |
}
|
1192 |
|
|
|
|
|
|
|
|
|
|
|
1193 |
public static function ImageExtFromMime($mime_type) {
|
1194 |
// temporary way, works OK for now, but should be reworked in the future
|
1195 |
return str_replace(array('image/', 'x-', 'jpeg'), array('', '', 'jpg'), $mime_type);
|
1196 |
}
|
1197 |
|
1198 |
-
|
1199 |
-
|
1200 |
-
|
1201 |
-
|
1202 |
-
|
1203 |
-
$ImageTypesLookup[3] = 'png';
|
1204 |
-
$ImageTypesLookup[4] = 'swf';
|
1205 |
-
$ImageTypesLookup[5] = 'psd';
|
1206 |
-
$ImageTypesLookup[6] = 'bmp';
|
1207 |
-
$ImageTypesLookup[7] = 'tiff (little-endian)';
|
1208 |
-
$ImageTypesLookup[8] = 'tiff (big-endian)';
|
1209 |
-
$ImageTypesLookup[9] = 'jpc';
|
1210 |
-
$ImageTypesLookup[10] = 'jp2';
|
1211 |
-
$ImageTypesLookup[11] = 'jpx';
|
1212 |
-
$ImageTypesLookup[12] = 'jb2';
|
1213 |
-
$ImageTypesLookup[13] = 'swc';
|
1214 |
-
$ImageTypesLookup[14] = 'iff';
|
1215 |
-
}
|
1216 |
-
return (isset($ImageTypesLookup[$imagetypeid]) ? $ImageTypesLookup[$imagetypeid] : '');
|
1217 |
-
}
|
1218 |
-
|
1219 |
public static function CopyTagsToComments(&$ThisFileInfo) {
|
1220 |
|
1221 |
// Copy all entries from ['tags'] into common ['comments']
|
@@ -1254,10 +1622,14 @@ class getid3_lib
|
|
1254 |
}
|
1255 |
if (is_array($value) || empty($ThisFileInfo['comments'][$tagname]) || !in_array(trim($value), $ThisFileInfo['comments'][$tagname])) {
|
1256 |
$value = (is_string($value) ? trim($value) : $value);
|
1257 |
-
if (!
|
1258 |
$ThisFileInfo['comments'][$tagname][$key] = $value;
|
1259 |
} else {
|
1260 |
-
$ThisFileInfo['comments'][$tagname]
|
|
|
|
|
|
|
|
|
1261 |
}
|
1262 |
}
|
1263 |
}
|
@@ -1265,6 +1637,18 @@ class getid3_lib
|
|
1265 |
}
|
1266 |
}
|
1267 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1268 |
// Copy to ['comments_html']
|
1269 |
if (!empty($ThisFileInfo['comments'])) {
|
1270 |
foreach ($ThisFileInfo['comments'] as $field => $values) {
|
@@ -1287,7 +1671,15 @@ class getid3_lib
|
|
1287 |
return true;
|
1288 |
}
|
1289 |
|
1290 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1291 |
public static function EmbeddedLookup($key, $begin, $end, $file, $name) {
|
1292 |
|
1293 |
// Cached
|
@@ -1334,6 +1726,14 @@ class getid3_lib
|
|
1334 |
return (isset($cache[$file][$name][$key]) ? $cache[$file][$name][$key] : '');
|
1335 |
}
|
1336 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1337 |
public static function IncludeDependency($filename, $sourcefile, $DieOnFailure=false) {
|
1338 |
global $GETID3_ERRORARRAY;
|
1339 |
|
@@ -1354,10 +1754,20 @@ class getid3_lib
|
|
1354 |
return false;
|
1355 |
}
|
1356 |
|
|
|
|
|
|
|
|
|
|
|
1357 |
public static function trimNullByte($string) {
|
1358 |
return trim($string, "\x00");
|
1359 |
}
|
1360 |
|
|
|
|
|
|
|
|
|
|
|
1361 |
public static function getFileSizeSyscall($path) {
|
1362 |
$filesize = false;
|
1363 |
|
@@ -1382,13 +1792,44 @@ class getid3_lib
|
|
1382 |
return $filesize;
|
1383 |
}
|
1384 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1385 |
|
1386 |
/**
|
1387 |
-
|
1388 |
-
|
1389 |
-
|
1390 |
-
|
1391 |
-
|
|
|
|
|
1392 |
public static function mb_basename($path, $suffix = null) {
|
1393 |
$splited = preg_split('#/#', rtrim($path, '/ '));
|
1394 |
return substr(basename('X'.$splited[count($splited) - 1], $suffix), 1);
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
|
|
8 |
// //
|
9 |
// getid3.lib.php - part of getID3() //
|
10 |
+
// see readme.txt for more details //
|
11 |
// ///
|
12 |
/////////////////////////////////////////////////////////////////
|
13 |
|
14 |
|
15 |
class getid3_lib
|
16 |
{
|
17 |
+
/**
|
18 |
+
* @param string $string
|
19 |
+
* @param bool $hex
|
20 |
+
* @param bool $spaces
|
21 |
+
* @param string $htmlencoding
|
22 |
+
*
|
23 |
+
* @return string
|
24 |
+
*/
|
25 |
public static function PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8') {
|
26 |
$returnstring = '';
|
27 |
for ($i = 0; $i < strlen($string); $i++) {
|
43 |
return $returnstring;
|
44 |
}
|
45 |
|
46 |
+
/**
|
47 |
+
* Truncates a floating-point number at the decimal point.
|
48 |
+
*
|
49 |
+
* @param float $floatnumber
|
50 |
+
*
|
51 |
+
* @return float|int returns int (if possible, otherwise float)
|
52 |
+
*/
|
53 |
public static function trunc($floatnumber) {
|
|
|
|
|
54 |
if ($floatnumber >= 1) {
|
55 |
$truncatednumber = floor($floatnumber);
|
56 |
} elseif ($floatnumber <= -1) {
|
64 |
return $truncatednumber;
|
65 |
}
|
66 |
|
67 |
+
/**
|
68 |
+
* @param int|null $variable
|
69 |
+
* @param int $increment
|
70 |
+
*
|
71 |
+
* @return bool
|
72 |
+
*/
|
73 |
public static function safe_inc(&$variable, $increment=1) {
|
74 |
if (isset($variable)) {
|
75 |
$variable += $increment;
|
79 |
return true;
|
80 |
}
|
81 |
|
82 |
+
/**
|
83 |
+
* @param int|float $floatnum
|
84 |
+
*
|
85 |
+
* @return int|float
|
86 |
+
*/
|
87 |
public static function CastAsInt($floatnum) {
|
88 |
// convert to float if not already
|
89 |
$floatnum = (float) $floatnum;
|
99 |
return $floatnum;
|
100 |
}
|
101 |
|
102 |
+
/**
|
103 |
+
* @param int $num
|
104 |
+
*
|
105 |
+
* @return bool
|
106 |
+
*/
|
107 |
public static function intValueSupported($num) {
|
108 |
// check if integers are 64-bit
|
109 |
static $hasINT64 = null;
|
120 |
return false;
|
121 |
}
|
122 |
|
123 |
+
/**
|
124 |
+
* @param string $fraction
|
125 |
+
*
|
126 |
+
* @return float
|
127 |
+
*/
|
128 |
public static function DecimalizeFraction($fraction) {
|
129 |
list($numerator, $denominator) = explode('/', $fraction);
|
130 |
return $numerator / ($denominator ? $denominator : 1);
|
131 |
}
|
132 |
|
133 |
+
/**
|
134 |
+
* @param string $binarynumerator
|
135 |
+
*
|
136 |
+
* @return float
|
137 |
+
*/
|
138 |
public static function DecimalBinary2Float($binarynumerator) {
|
139 |
$numerator = self::Bin2Dec($binarynumerator);
|
140 |
$denominator = self::Bin2Dec('1'.str_repeat('0', strlen($binarynumerator)));
|
141 |
return ($numerator / $denominator);
|
142 |
}
|
143 |
|
144 |
+
/**
|
145 |
+
* @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
|
146 |
+
*
|
147 |
+
* @param string $binarypointnumber
|
148 |
+
* @param int $maxbits
|
149 |
+
*
|
150 |
+
* @return array
|
151 |
+
*/
|
152 |
public static function NormalizeBinaryPoint($binarypointnumber, $maxbits=52) {
|
|
|
153 |
if (strpos($binarypointnumber, '.') === false) {
|
154 |
$binarypointnumber = '0.'.$binarypointnumber;
|
155 |
} elseif ($binarypointnumber{0} == '.') {
|
171 |
return array('normalized'=>$binarypointnumber, 'exponent'=>(int) $exponent);
|
172 |
}
|
173 |
|
174 |
+
/**
|
175 |
+
* @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
|
176 |
+
*
|
177 |
+
* @param float $floatvalue
|
178 |
+
*
|
179 |
+
* @return string
|
180 |
+
*/
|
181 |
public static function Float2BinaryDecimal($floatvalue) {
|
|
|
182 |
$maxbits = 128; // to how many bits of precision should the calculations be taken?
|
183 |
$intpart = self::trunc($floatvalue);
|
184 |
$floatpart = abs($floatvalue - $intpart);
|
192 |
return $binarypointnumber;
|
193 |
}
|
194 |
|
195 |
+
/**
|
196 |
+
* @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html
|
197 |
+
*
|
198 |
+
* @param float $floatvalue
|
199 |
+
* @param int $bits
|
200 |
+
*
|
201 |
+
* @return string|false
|
202 |
+
*/
|
203 |
public static function Float2String($floatvalue, $bits) {
|
204 |
+
$exponentbits = 0;
|
205 |
+
$fractionbits = 0;
|
206 |
switch ($bits) {
|
207 |
case 32:
|
208 |
$exponentbits = 8;
|
231 |
return self::BigEndian2String(self::Bin2Dec($signbit.$exponentbitstring.$fractionbitstring), $bits % 8, false);
|
232 |
}
|
233 |
|
234 |
+
/**
|
235 |
+
* @param string $byteword
|
236 |
+
*
|
237 |
+
* @return float|false
|
238 |
+
*/
|
239 |
public static function LittleEndian2Float($byteword) {
|
240 |
return self::BigEndian2Float(strrev($byteword));
|
241 |
}
|
242 |
|
243 |
+
/**
|
244 |
+
* ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic
|
245 |
+
*
|
246 |
+
* @link http://www.psc.edu/general/software/packages/ieee/ieee.html
|
247 |
+
* @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html
|
248 |
+
*
|
249 |
+
* @param string $byteword
|
250 |
+
*
|
251 |
+
* @return float|false
|
252 |
+
*/
|
253 |
public static function BigEndian2Float($byteword) {
|
|
|
|
|
|
|
|
|
254 |
$bitword = self::BigEndian2Bin($byteword);
|
255 |
if (!$bitword) {
|
256 |
return 0;
|
257 |
}
|
258 |
$signbit = $bitword{0};
|
259 |
+
$floatvalue = 0;
|
260 |
+
$exponentbits = 0;
|
261 |
+
$fractionbits = 0;
|
262 |
|
263 |
switch (strlen($byteword) * 8) {
|
264 |
case 32:
|
326 |
return (float) $floatvalue;
|
327 |
}
|
328 |
|
329 |
+
/**
|
330 |
+
* @param string $byteword
|
331 |
+
* @param bool $synchsafe
|
332 |
+
* @param bool $signed
|
333 |
+
*
|
334 |
+
* @return int|float|false
|
335 |
+
* @throws Exception
|
336 |
+
*/
|
337 |
public static function BigEndian2Int($byteword, $synchsafe=false, $signed=false) {
|
338 |
$intvalue = 0;
|
339 |
$bytewordlen = strlen($byteword);
|
362 |
return self::CastAsInt($intvalue);
|
363 |
}
|
364 |
|
365 |
+
/**
|
366 |
+
* @param string $byteword
|
367 |
+
* @param bool $signed
|
368 |
+
*
|
369 |
+
* @return int|float|false
|
370 |
+
*/
|
371 |
public static function LittleEndian2Int($byteword, $signed=false) {
|
372 |
return self::BigEndian2Int(strrev($byteword), false, $signed);
|
373 |
}
|
374 |
|
375 |
+
/**
|
376 |
+
* @param string $byteword
|
377 |
+
*
|
378 |
+
* @return string
|
379 |
+
*/
|
380 |
+
public static function LittleEndian2Bin($byteword) {
|
381 |
+
return self::BigEndian2Bin(strrev($byteword));
|
382 |
+
}
|
383 |
|
384 |
+
/**
|
385 |
+
* @param string $byteword
|
386 |
+
*
|
387 |
+
* @return string
|
388 |
+
*/
|
389 |
public static function BigEndian2Bin($byteword) {
|
390 |
$binvalue = '';
|
391 |
$bytewordlen = strlen($byteword);
|
395 |
return $binvalue;
|
396 |
}
|
397 |
|
398 |
+
/**
|
399 |
+
* @param int $number
|
400 |
+
* @param int $minbytes
|
401 |
+
* @param bool $synchsafe
|
402 |
+
* @param bool $signed
|
403 |
+
*
|
404 |
+
* @return string
|
405 |
+
* @throws Exception
|
406 |
+
*/
|
407 |
public static function BigEndian2String($number, $minbytes=1, $synchsafe=false, $signed=false) {
|
408 |
if ($number < 0) {
|
409 |
throw new Exception('ERROR: self::BigEndian2String() does not support negative numbers');
|
424 |
return str_pad($intstring, $minbytes, "\x00", STR_PAD_LEFT);
|
425 |
}
|
426 |
|
427 |
+
/**
|
428 |
+
* @param int $number
|
429 |
+
*
|
430 |
+
* @return string
|
431 |
+
*/
|
432 |
public static function Dec2Bin($number) {
|
433 |
while ($number >= 256) {
|
434 |
$bytes[] = (($number / 256) - (floor($number / 256))) * 256;
|
442 |
return $binstring;
|
443 |
}
|
444 |
|
445 |
+
/**
|
446 |
+
* @param string $binstring
|
447 |
+
* @param bool $signed
|
448 |
+
*
|
449 |
+
* @return int|float
|
450 |
+
*/
|
451 |
public static function Bin2Dec($binstring, $signed=false) {
|
452 |
$signmult = 1;
|
453 |
if ($signed) {
|
463 |
return self::CastAsInt($decvalue * $signmult);
|
464 |
}
|
465 |
|
466 |
+
/**
|
467 |
+
* @param string $binstring
|
468 |
+
*
|
469 |
+
* @return string
|
470 |
+
*/
|
471 |
public static function Bin2String($binstring) {
|
472 |
// return 'hi' for input of '0110100001101001'
|
473 |
$string = '';
|
478 |
return $string;
|
479 |
}
|
480 |
|
481 |
+
/**
|
482 |
+
* @param int $number
|
483 |
+
* @param int $minbytes
|
484 |
+
* @param bool $synchsafe
|
485 |
+
*
|
486 |
+
* @return string
|
487 |
+
*/
|
488 |
public static function LittleEndian2String($number, $minbytes=1, $synchsafe=false) {
|
489 |
$intstring = '';
|
490 |
while ($number > 0) {
|
499 |
return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT);
|
500 |
}
|
501 |
|
502 |
+
/**
|
503 |
+
* @param array $array1
|
504 |
+
* @param array $array2
|
505 |
+
*
|
506 |
+
* @return array|false
|
507 |
+
*/
|
508 |
public static function array_merge_clobber($array1, $array2) {
|
509 |
// written by kcØhireability*com
|
510 |
// taken from http://www.php.net/manual/en/function.array-merge-recursive.php
|
522 |
return $newarray;
|
523 |
}
|
524 |
|
525 |
+
/**
|
526 |
+
* @param array $array1
|
527 |
+
* @param array $array2
|
528 |
+
*
|
529 |
+
* @return array|false
|
530 |
+
*/
|
531 |
public static function array_merge_noclobber($array1, $array2) {
|
532 |
if (!is_array($array1) || !is_array($array2)) {
|
533 |
return false;
|
543 |
return $newarray;
|
544 |
}
|
545 |
|
546 |
+
/**
|
547 |
+
* @param array $array1
|
548 |
+
* @param array $array2
|
549 |
+
*
|
550 |
+
* @return array|false|null
|
551 |
+
*/
|
552 |
public static function flipped_array_merge_noclobber($array1, $array2) {
|
553 |
if (!is_array($array1) || !is_array($array2)) {
|
554 |
return false;
|
563 |
return array_flip($newarray);
|
564 |
}
|
565 |
|
566 |
+
/**
|
567 |
+
* @param array $theArray
|
568 |
+
*
|
569 |
+
* @return bool
|
570 |
+
*/
|
571 |
public static function ksort_recursive(&$theArray) {
|
572 |
ksort($theArray);
|
573 |
foreach ($theArray as $key => $value) {
|
578 |
return true;
|
579 |
}
|
580 |
|
581 |
+
/**
|
582 |
+
* @param string $filename
|
583 |
+
* @param int $numextensions
|
584 |
+
*
|
585 |
+
* @return string
|
586 |
+
*/
|
587 |
public static function fileextension($filename, $numextensions=1) {
|
588 |
if (strstr($filename, '.')) {
|
589 |
$reversedfilename = strrev($filename);
|
599 |
return '';
|
600 |
}
|
601 |
|
602 |
+
/**
|
603 |
+
* @param int $seconds
|
604 |
+
*
|
605 |
+
* @return string
|
606 |
+
*/
|
607 |
public static function PlaytimeString($seconds) {
|
608 |
$sign = (($seconds < 0) ? '-' : '');
|
609 |
$seconds = round(abs($seconds));
|
613 |
return $sign.($H ? $H.':' : '').($H ? str_pad($M, 2, '0', STR_PAD_LEFT) : intval($M)).':'.str_pad($S, 2, 0, STR_PAD_LEFT);
|
614 |
}
|
615 |
|
616 |
+
/**
|
617 |
+
* @param int $macdate
|
618 |
+
*
|
619 |
+
* @return int|float
|
620 |
+
*/
|
621 |
public static function DateMac2Unix($macdate) {
|
622 |
// Macintosh timestamp: seconds since 00:00h January 1, 1904
|
623 |
// UNIX timestamp: seconds since 00:00h January 1, 1970
|
624 |
return self::CastAsInt($macdate - 2082844800);
|
625 |
}
|
626 |
|
627 |
+
/**
|
628 |
+
* @param string $rawdata
|
629 |
+
*
|
630 |
+
* @return float
|
631 |
+
*/
|
632 |
public static function FixedPoint8_8($rawdata) {
|
633 |
return self::BigEndian2Int(substr($rawdata, 0, 1)) + (float) (self::BigEndian2Int(substr($rawdata, 1, 1)) / pow(2, 8));
|
634 |
}
|
635 |
|
636 |
+
/**
|
637 |
+
* @param string $rawdata
|
638 |
+
*
|
639 |
+
* @return float
|
640 |
+
*/
|
641 |
public static function FixedPoint16_16($rawdata) {
|
642 |
return self::BigEndian2Int(substr($rawdata, 0, 2)) + (float) (self::BigEndian2Int(substr($rawdata, 2, 2)) / pow(2, 16));
|
643 |
}
|
644 |
|
645 |
+
/**
|
646 |
+
* @param string $rawdata
|
647 |
+
*
|
648 |
+
* @return float
|
649 |
+
*/
|
650 |
public static function FixedPoint2_30($rawdata) {
|
651 |
$binarystring = self::BigEndian2Bin($rawdata);
|
652 |
return self::Bin2Dec(substr($binarystring, 0, 2)) + (float) (self::Bin2Dec(substr($binarystring, 2, 30)) / pow(2, 30));
|
653 |
}
|
654 |
|
655 |
|
656 |
+
/**
|
657 |
+
* @param string $ArrayPath
|
658 |
+
* @param string $Separator
|
659 |
+
* @param mixed $Value
|
660 |
+
*
|
661 |
+
* @return array
|
662 |
+
*/
|
663 |
public static function CreateDeepArray($ArrayPath, $Separator, $Value) {
|
664 |
// assigns $Value to a nested array path:
|
665 |
// $foo = self::CreateDeepArray('/path/to/my', '/', 'file.txt')
|
676 |
return $ReturnedArray;
|
677 |
}
|
678 |
|
679 |
+
/**
|
680 |
+
* @param array $arraydata
|
681 |
+
* @param bool $returnkey
|
682 |
+
*
|
683 |
+
* @return int|false
|
684 |
+
*/
|
685 |
public static function array_max($arraydata, $returnkey=false) {
|
686 |
$maxvalue = false;
|
687 |
$maxkey = false;
|
696 |
return ($returnkey ? $maxkey : $maxvalue);
|
697 |
}
|
698 |
|
699 |
+
/**
|
700 |
+
* @param array $arraydata
|
701 |
+
* @param bool $returnkey
|
702 |
+
*
|
703 |
+
* @return int|false
|
704 |
+
*/
|
705 |
public static function array_min($arraydata, $returnkey=false) {
|
706 |
$minvalue = false;
|
707 |
$minkey = false;
|
716 |
return ($returnkey ? $minkey : $minvalue);
|
717 |
}
|
718 |
|
719 |
+
/**
|
720 |
+
* @param string $XMLstring
|
721 |
+
*
|
722 |
+
* @return array|false
|
723 |
+
*/
|
724 |
public static function XML2array($XMLstring) {
|
725 |
if (function_exists('simplexml_load_string') && function_exists('libxml_disable_entity_loader')) {
|
726 |
// http://websec.io/2012/08/27/Preventing-XEE-in-PHP.html
|
734 |
return false;
|
735 |
}
|
736 |
|
737 |
+
/**
|
738 |
+
* @param SimpleXMLElement|array $XMLobject
|
739 |
+
*
|
740 |
+
* @return array
|
741 |
+
*/
|
742 |
public static function SimpleXMLelement2array($XMLobject) {
|
743 |
if (!is_object($XMLobject) && !is_array($XMLobject)) {
|
744 |
return $XMLobject;
|
745 |
}
|
746 |
+
$XMLarray = $XMLobject instanceof SimpleXMLElement ? get_object_vars($XMLobject) : $XMLobject;
|
747 |
foreach ($XMLarray as $key => $value) {
|
748 |
$XMLarray[$key] = self::SimpleXMLelement2array($value);
|
749 |
}
|
750 |
return $XMLarray;
|
751 |
}
|
752 |
|
753 |
+
/**
|
754 |
+
* self::md5_data() - returns md5sum for a file from startuing position to absolute end position
|
755 |
+
*
|
756 |
+
* @author Allan Hansen <ahØartemis*dk>
|
757 |
+
*
|
758 |
+
* @param string $file
|
759 |
+
* @param int $offset
|
760 |
+
* @param int $end
|
761 |
+
* @param string $algorithm
|
762 |
+
*
|
763 |
+
* @return string|false
|
764 |
+
* @throws Exception
|
765 |
+
* @throws getid3_exception
|
766 |
+
*/
|
767 |
public static function hash_data($file, $offset, $end, $algorithm) {
|
768 |
static $tempdir = '';
|
769 |
+
$windows_call = null;
|
770 |
+
$unix_call = null;
|
771 |
+
$hash_length = null;
|
772 |
+
$hash_function = null;
|
773 |
if (!self::intValueSupported($end)) {
|
774 |
return false;
|
775 |
}
|
854 |
return $result;
|
855 |
}
|
856 |
|
857 |
+
/**
|
858 |
+
* @param string $filename_source
|
859 |
+
* @param string $filename_dest
|
860 |
+
* @param int $offset
|
861 |
+
* @param int $length
|
862 |
+
*
|
863 |
+
* @return bool
|
864 |
+
* @throws Exception
|
865 |
+
*/
|
866 |
public static function CopyFileParts($filename_source, $filename_dest, $offset, $length) {
|
867 |
if (!self::intValueSupported($offset + $length)) {
|
868 |
throw new Exception('cannot copy file portion, it extends beyond the '.round(PHP_INT_MAX / 1073741824).'GB limit');
|
875 |
$byteswritten = fwrite($fp_dest, $buffer, $byteslefttowrite);
|
876 |
$byteslefttowrite -= $byteswritten;
|
877 |
}
|
878 |
+
fclose($fp_dest);
|
879 |
return true;
|
880 |
} else {
|
881 |
+
fclose($fp_src);
|
882 |
throw new Exception('failed to seek to offset '.$offset.' in '.$filename_source);
|
883 |
}
|
|
|
884 |
} else {
|
885 |
throw new Exception('failed to create file for writing '.$filename_dest);
|
886 |
}
|
|
|
887 |
} else {
|
888 |
throw new Exception('failed to open file for reading '.$filename_source);
|
889 |
}
|
|
|
890 |
}
|
891 |
|
892 |
+
/**
|
893 |
+
* @param int $charval
|
894 |
+
*
|
895 |
+
* @return string
|
896 |
+
*/
|
897 |
public static function iconv_fallback_int_utf8($charval) {
|
898 |
if ($charval < 128) {
|
899 |
// 0bbbbbbb
|
917 |
return $newcharstring;
|
918 |
}
|
919 |
|
920 |
+
/**
|
921 |
+
* ISO-8859-1 => UTF-8
|
922 |
+
*
|
923 |
+
* @param string $string
|
924 |
+
* @param bool $bom
|
925 |
+
*
|
926 |
+
* @return string
|
927 |
+
*/
|
928 |
public static function iconv_fallback_iso88591_utf8($string, $bom=false) {
|
929 |
if (function_exists('utf8_encode')) {
|
930 |
return utf8_encode($string);
|
941 |
return $newcharstring;
|
942 |
}
|
943 |
|
944 |
+
/**
|
945 |
+
* ISO-8859-1 => UTF-16BE
|
946 |
+
*
|
947 |
+
* @param string $string
|
948 |
+
* @param bool $bom
|
949 |
+
*
|
950 |
+
* @return string
|
951 |
+
*/
|
952 |
public static function iconv_fallback_iso88591_utf16be($string, $bom=false) {
|
953 |
$newcharstring = '';
|
954 |
if ($bom) {
|
960 |
return $newcharstring;
|
961 |
}
|
962 |
|
963 |
+
/**
|
964 |
+
* ISO-8859-1 => UTF-16LE
|
965 |
+
*
|
966 |
+
* @param string $string
|
967 |
+
* @param bool $bom
|
968 |
+
*
|
969 |
+
* @return string
|
970 |
+
*/
|
971 |
public static function iconv_fallback_iso88591_utf16le($string, $bom=false) {
|
972 |
$newcharstring = '';
|
973 |
if ($bom) {
|
979 |
return $newcharstring;
|
980 |
}
|
981 |
|
982 |
+
/**
|
983 |
+
* ISO-8859-1 => UTF-16LE (BOM)
|
984 |
+
*
|
985 |
+
* @param string $string
|
986 |
+
*
|
987 |
+
* @return string
|
988 |
+
*/
|
989 |
public static function iconv_fallback_iso88591_utf16($string) {
|
990 |
return self::iconv_fallback_iso88591_utf16le($string, true);
|
991 |
}
|
992 |
|
993 |
+
/**
|
994 |
+
* UTF-8 => ISO-8859-1
|
995 |
+
*
|
996 |
+
* @param string $string
|
997 |
+
*
|
998 |
+
* @return string
|
999 |
+
*/
|
1000 |
public static function iconv_fallback_utf8_iso88591($string) {
|
1001 |
if (function_exists('utf8_decode')) {
|
1002 |
return utf8_decode($string);
|
1040 |
return $newcharstring;
|
1041 |
}
|
1042 |
|
1043 |
+
/**
|
1044 |
+
* UTF-8 => UTF-16BE
|
1045 |
+
*
|
1046 |
+
* @param string $string
|
1047 |
+
* @param bool $bom
|
1048 |
+
*
|
1049 |
+
* @return string
|
1050 |
+
*/
|
1051 |
public static function iconv_fallback_utf8_utf16be($string, $bom=false) {
|
1052 |
$newcharstring = '';
|
1053 |
if ($bom) {
|
1090 |
return $newcharstring;
|
1091 |
}
|
1092 |
|
1093 |
+
/**
|
1094 |
+
* UTF-8 => UTF-16LE
|
1095 |
+
*
|
1096 |
+
* @param string $string
|
1097 |
+
* @param bool $bom
|
1098 |
+
*
|
1099 |
+
* @return string
|
1100 |
+
*/
|
1101 |
public static function iconv_fallback_utf8_utf16le($string, $bom=false) {
|
1102 |
$newcharstring = '';
|
1103 |
if ($bom) {
|
1140 |
return $newcharstring;
|
1141 |
}
|
1142 |
|
1143 |
+
/**
|
1144 |
+
* UTF-8 => UTF-16LE (BOM)
|
1145 |
+
*
|
1146 |
+
* @param string $string
|
1147 |
+
*
|
1148 |
+
* @return string
|
1149 |
+
*/
|
1150 |
public static function iconv_fallback_utf8_utf16($string) {
|
1151 |
return self::iconv_fallback_utf8_utf16le($string, true);
|
1152 |
}
|
1153 |
|
1154 |
+
/**
|
1155 |
+
* UTF-16BE => UTF-8
|
1156 |
+
*
|
1157 |
+
* @param string $string
|
1158 |
+
*
|
1159 |
+
* @return string
|
1160 |
+
*/
|
1161 |
public static function iconv_fallback_utf16be_utf8($string) {
|
1162 |
if (substr($string, 0, 2) == "\xFE\xFF") {
|
1163 |
// strip BOM
|
1171 |
return $newcharstring;
|
1172 |
}
|
1173 |
|
1174 |
+
/**
|
1175 |
+
* UTF-16LE => UTF-8
|
1176 |
+
*
|
1177 |
+
* @param string $string
|
1178 |
+
*
|
1179 |
+
* @return string
|
1180 |
+
*/
|
1181 |
public static function iconv_fallback_utf16le_utf8($string) {
|
1182 |
if (substr($string, 0, 2) == "\xFF\xFE") {
|
1183 |
// strip BOM
|
1191 |
return $newcharstring;
|
1192 |
}
|
1193 |
|
1194 |
+
/**
|
1195 |
+
* UTF-16BE => ISO-8859-1
|
1196 |
+
*
|
1197 |
+
* @param string $string
|
1198 |
+
*
|
1199 |
+
* @return string
|
1200 |
+
*/
|
1201 |
public static function iconv_fallback_utf16be_iso88591($string) {
|
1202 |
if (substr($string, 0, 2) == "\xFE\xFF") {
|
1203 |
// strip BOM
|
1211 |
return $newcharstring;
|
1212 |
}
|
1213 |
|
1214 |
+
/**
|
1215 |
+
* UTF-16LE => ISO-8859-1
|
1216 |
+
*
|
1217 |
+
* @param string $string
|
1218 |
+
*
|
1219 |
+
* @return string
|
1220 |
+
*/
|
1221 |
public static function iconv_fallback_utf16le_iso88591($string) {
|
1222 |
if (substr($string, 0, 2) == "\xFF\xFE") {
|
1223 |
// strip BOM
|
1231 |
return $newcharstring;
|
1232 |
}
|
1233 |
|
1234 |
+
/**
|
1235 |
+
* UTF-16 (BOM) => ISO-8859-1
|
1236 |
+
*
|
1237 |
+
* @param string $string
|
1238 |
+
*
|
1239 |
+
* @return string
|
1240 |
+
*/
|
1241 |
public static function iconv_fallback_utf16_iso88591($string) {
|
1242 |
$bom = substr($string, 0, 2);
|
1243 |
if ($bom == "\xFE\xFF") {
|
1248 |
return $string;
|
1249 |
}
|
1250 |
|
1251 |
+
/**
|
1252 |
+
* UTF-16 (BOM) => UTF-8
|
1253 |
+
*
|
1254 |
+
* @param string $string
|
1255 |
+
*
|
1256 |
+
* @return string
|
1257 |
+
*/
|
1258 |
public static function iconv_fallback_utf16_utf8($string) {
|
1259 |
$bom = substr($string, 0, 2);
|
1260 |
if ($bom == "\xFE\xFF") {
|
1265 |
return $string;
|
1266 |
}
|
1267 |
|
1268 |
+
/**
|
1269 |
+
* @param string $in_charset
|
1270 |
+
* @param string $out_charset
|
1271 |
+
* @param string $string
|
1272 |
+
*
|
1273 |
+
* @return string
|
1274 |
+
* @throws Exception
|
1275 |
+
*/
|
1276 |
public static function iconv_fallback($in_charset, $out_charset, $string) {
|
1277 |
|
1278 |
if ($in_charset == $out_charset) {
|
1279 |
return $string;
|
1280 |
}
|
1281 |
|
1282 |
+
// mb_convert_encoding() available
|
1283 |
+
if (function_exists('mb_convert_encoding')) {
|
1284 |
+
if ($converted_string = @mb_convert_encoding($string, $out_charset, $in_charset)) {
|
1285 |
+
switch ($out_charset) {
|
1286 |
+
case 'ISO-8859-1':
|
1287 |
+
$converted_string = rtrim($converted_string, "\x00");
|
1288 |
+
break;
|
1289 |
+
}
|
1290 |
+
return $converted_string;
|
1291 |
+
}
|
1292 |
+
return $string;
|
1293 |
+
}
|
1294 |
+
// iconv() available
|
1295 |
+
else if (function_exists('iconv')) {
|
1296 |
if ($converted_string = @iconv($in_charset, $out_charset.'//TRANSLIT', $string)) {
|
1297 |
switch ($out_charset) {
|
1298 |
case 'ISO-8859-1':
|
1308 |
}
|
1309 |
|
1310 |
|
1311 |
+
// neither mb_convert_encoding or iconv() is available
|
1312 |
static $ConversionFunctionList = array();
|
1313 |
if (empty($ConversionFunctionList)) {
|
1314 |
$ConversionFunctionList['ISO-8859-1']['UTF-8'] = 'iconv_fallback_iso88591_utf8';
|
1330 |
$ConversionFunction = $ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)];
|
1331 |
return self::$ConversionFunction($string);
|
1332 |
}
|
1333 |
+
throw new Exception('PHP does not has mb_convert_encoding() or iconv() support - cannot convert from '.$in_charset.' to '.$out_charset);
|
1334 |
}
|
1335 |
|
1336 |
+
/**
|
1337 |
+
* @param mixed $data
|
1338 |
+
* @param string $charset
|
1339 |
+
*
|
1340 |
+
* @return mixed
|
1341 |
+
*/
|
1342 |
public static function recursiveMultiByteCharString2HTML($data, $charset='ISO-8859-1') {
|
1343 |
if (is_string($data)) {
|
1344 |
return self::MultiByteCharString2HTML($data, $charset);
|
1353 |
return $data;
|
1354 |
}
|
1355 |
|
1356 |
+
/**
|
1357 |
+
* @param string|int|float $string
|
1358 |
+
* @param string $charset
|
1359 |
+
*
|
1360 |
+
* @return string
|
1361 |
+
*/
|
1362 |
public static function MultiByteCharString2HTML($string, $charset='ISO-8859-1') {
|
1363 |
$string = (string) $string; // in case trying to pass a numeric (float, int) string, would otherwise return an empty string
|
1364 |
$HTMLstring = '';
|
1365 |
|
1366 |
+
switch (strtolower($charset)) {
|
1367 |
case '1251':
|
1368 |
case '1252':
|
1369 |
case '866':
|
1370 |
case '932':
|
1371 |
case '936':
|
1372 |
case '950':
|
1373 |
+
case 'big5':
|
1374 |
+
case 'big5-hkscs':
|
1375 |
case 'cp1251':
|
1376 |
case 'cp1252':
|
1377 |
case 'cp866':
|
1378 |
+
case 'euc-jp':
|
1379 |
+
case 'eucjp':
|
1380 |
+
case 'gb2312':
|
1381 |
case 'ibm866':
|
1382 |
+
case 'iso-8859-1':
|
1383 |
+
case 'iso-8859-15':
|
1384 |
+
case 'iso8859-1':
|
1385 |
+
case 'iso8859-15':
|
1386 |
+
case 'koi8-r':
|
1387 |
case 'koi8-ru':
|
1388 |
case 'koi8r':
|
1389 |
+
case 'shift_jis':
|
1390 |
+
case 'sjis':
|
1391 |
case 'win-1251':
|
1392 |
+
case 'windows-1251':
|
1393 |
+
case 'windows-1252':
|
1394 |
$HTMLstring = htmlentities($string, ENT_COMPAT, $charset);
|
1395 |
break;
|
1396 |
|
1397 |
+
case 'utf-8':
|
1398 |
$strlen = strlen($string);
|
1399 |
for ($i = 0; $i < $strlen; $i++) {
|
1400 |
$char_ord_val = ord($string{$i});
|
1422 |
}
|
1423 |
break;
|
1424 |
|
1425 |
+
case 'utf-16le':
|
1426 |
for ($i = 0; $i < strlen($string); $i += 2) {
|
1427 |
$charval = self::LittleEndian2Int(substr($string, $i, 2));
|
1428 |
if (($charval >= 32) && ($charval <= 127)) {
|
1433 |
}
|
1434 |
break;
|
1435 |
|
1436 |
+
case 'utf-16be':
|
1437 |
for ($i = 0; $i < strlen($string); $i += 2) {
|
1438 |
$charval = self::BigEndian2Int(substr($string, $i, 2));
|
1439 |
if (($charval >= 32) && ($charval <= 127)) {
|
1451 |
return $HTMLstring;
|
1452 |
}
|
1453 |
|
1454 |
+
/**
|
1455 |
+
* @param int $namecode
|
1456 |
+
*
|
1457 |
+
* @return string
|
1458 |
+
*/
|
1459 |
public static function RGADnameLookup($namecode) {
|
1460 |
static $RGADname = array();
|
1461 |
if (empty($RGADname)) {
|
1467 |
return (isset($RGADname[$namecode]) ? $RGADname[$namecode] : '');
|
1468 |
}
|
1469 |
|
1470 |
+
/**
|
1471 |
+
* @param int $originatorcode
|
1472 |
+
*
|
1473 |
+
* @return string
|
1474 |
+
*/
|
1475 |
public static function RGADoriginatorLookup($originatorcode) {
|
1476 |
static $RGADoriginator = array();
|
1477 |
if (empty($RGADoriginator)) {
|
1484 |
return (isset($RGADoriginator[$originatorcode]) ? $RGADoriginator[$originatorcode] : '');
|
1485 |
}
|
1486 |
|
1487 |
+
/**
|
1488 |
+
* @param int $rawadjustment
|
1489 |
+
* @param int $signbit
|
1490 |
+
*
|
1491 |
+
* @return float
|
1492 |
+
*/
|
1493 |
public static function RGADadjustmentLookup($rawadjustment, $signbit) {
|
1494 |
+
$adjustment = (float) $rawadjustment / 10;
|
1495 |
if ($signbit == 1) {
|
1496 |
$adjustment *= -1;
|
1497 |
}
|
1498 |
+
return $adjustment;
|
1499 |
}
|
1500 |
|
1501 |
+
/**
|
1502 |
+
* @param int $namecode
|
1503 |
+
* @param int $originatorcode
|
1504 |
+
* @param int $replaygain
|
1505 |
+
*
|
1506 |
+
* @return string
|
1507 |
+
*/
|
1508 |
public static function RGADgainString($namecode, $originatorcode, $replaygain) {
|
1509 |
if ($replaygain < 0) {
|
1510 |
$signbit = '1';
|
1520 |
return $gainstring;
|
1521 |
}
|
1522 |
|
1523 |
+
/**
|
1524 |
+
* @param float $amplitude
|
1525 |
+
*
|
1526 |
+
* @return float
|
1527 |
+
*/
|
1528 |
public static function RGADamplitude2dB($amplitude) {
|
1529 |
return 20 * log10($amplitude);
|
1530 |
}
|
1531 |
|
1532 |
+
/**
|
1533 |
+
* @param string $imgData
|
1534 |
+
* @param array $imageinfo
|
1535 |
+
*
|
1536 |
+
* @return array|false
|
1537 |
+
*/
|
1538 |
public static function GetDataImageSize($imgData, &$imageinfo=array()) {
|
1539 |
static $tempdir = '';
|
1540 |
if (empty($tempdir)) {
|
1541 |
+
if (function_exists('sys_get_temp_dir')) {
|
1542 |
+
$tempdir = sys_get_temp_dir(); // https://github.com/JamesHeinrich/getID3/issues/52
|
1543 |
+
}
|
1544 |
+
|
1545 |
// yes this is ugly, feel free to suggest a better way
|
1546 |
+
if (include_once(dirname(__FILE__).'/getid3.php')) {
|
1547 |
+
if ($getid3_temp = new getID3()) {
|
1548 |
+
if ($getid3_temp_tempdir = $getid3_temp->tempdir) {
|
1549 |
+
$tempdir = $getid3_temp_tempdir;
|
1550 |
+
}
|
1551 |
+
unset($getid3_temp, $getid3_temp_tempdir);
|
1552 |
+
}
|
1553 |
+
}
|
1554 |
}
|
1555 |
$GetDataImageSize = false;
|
1556 |
if ($tempfilename = tempnam($tempdir, 'gI3')) {
|
1569 |
return $GetDataImageSize;
|
1570 |
}
|
1571 |
|
1572 |
+
/**
|
1573 |
+
* @param string $mime_type
|
1574 |
+
*
|
1575 |
+
* @return string
|
1576 |
+
*/
|
1577 |
public static function ImageExtFromMime($mime_type) {
|
1578 |
// temporary way, works OK for now, but should be reworked in the future
|
1579 |
return str_replace(array('image/', 'x-', 'jpeg'), array('', '', 'jpg'), $mime_type);
|
1580 |
}
|
1581 |
|
1582 |
+
/**
|
1583 |
+
* @param array $ThisFileInfo
|
1584 |
+
*
|
1585 |
+
* @return bool
|
1586 |
+
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1587 |
public static function CopyTagsToComments(&$ThisFileInfo) {
|
1588 |
|
1589 |
// Copy all entries from ['tags'] into common ['comments']
|
1622 |
}
|
1623 |
if (is_array($value) || empty($ThisFileInfo['comments'][$tagname]) || !in_array(trim($value), $ThisFileInfo['comments'][$tagname])) {
|
1624 |
$value = (is_string($value) ? trim($value) : $value);
|
1625 |
+
if (!is_int($key) && !ctype_digit($key)) {
|
1626 |
$ThisFileInfo['comments'][$tagname][$key] = $value;
|
1627 |
} else {
|
1628 |
+
if (isset($ThisFileInfo['comments'][$tagname])) {
|
1629 |
+
$ThisFileInfo['comments'][$tagname] = array($value);
|
1630 |
+
} else {
|
1631 |
+
$ThisFileInfo['comments'][$tagname][] = $value;
|
1632 |
+
}
|
1633 |
}
|
1634 |
}
|
1635 |
}
|
1637 |
}
|
1638 |
}
|
1639 |
|
1640 |
+
// attempt to standardize spelling of returned keys
|
1641 |
+
$StandardizeFieldNames = array(
|
1642 |
+
'tracknumber' => 'track_number',
|
1643 |
+
'track' => 'track_number',
|
1644 |
+
);
|
1645 |
+
foreach ($StandardizeFieldNames as $badkey => $goodkey) {
|
1646 |
+
if (array_key_exists($badkey, $ThisFileInfo['comments']) && !array_key_exists($goodkey, $ThisFileInfo['comments'])) {
|
1647 |
+
$ThisFileInfo['comments'][$goodkey] = $ThisFileInfo['comments'][$badkey];
|
1648 |
+
unset($ThisFileInfo['comments'][$badkey]);
|
1649 |
+
}
|
1650 |
+
}
|
1651 |
+
|
1652 |
// Copy to ['comments_html']
|
1653 |
if (!empty($ThisFileInfo['comments'])) {
|
1654 |
foreach ($ThisFileInfo['comments'] as $field => $values) {
|
1671 |
return true;
|
1672 |
}
|
1673 |
|
1674 |
+
/**
|
1675 |
+
* @param string $key
|
1676 |
+
* @param int $begin
|
1677 |
+
* @param int $end
|
1678 |
+
* @param string $file
|
1679 |
+
* @param string $name
|
1680 |
+
*
|
1681 |
+
* @return string
|
1682 |
+
*/
|
1683 |
public static function EmbeddedLookup($key, $begin, $end, $file, $name) {
|
1684 |
|
1685 |
// Cached
|
1726 |
return (isset($cache[$file][$name][$key]) ? $cache[$file][$name][$key] : '');
|
1727 |
}
|
1728 |
|
1729 |
+
/**
|
1730 |
+
* @param string $filename
|
1731 |
+
* @param string $sourcefile
|
1732 |
+
* @param bool $DieOnFailure
|
1733 |
+
*
|
1734 |
+
* @return bool
|
1735 |
+
* @throws Exception
|
1736 |
+
*/
|
1737 |
public static function IncludeDependency($filename, $sourcefile, $DieOnFailure=false) {
|
1738 |
global $GETID3_ERRORARRAY;
|
1739 |
|
1754 |
return false;
|
1755 |
}
|
1756 |
|
1757 |
+
/**
|
1758 |
+
* @param string $string
|
1759 |
+
*
|
1760 |
+
* @return string
|
1761 |
+
*/
|
1762 |
public static function trimNullByte($string) {
|
1763 |
return trim($string, "\x00");
|
1764 |
}
|
1765 |
|
1766 |
+
/**
|
1767 |
+
* @param string $path
|
1768 |
+
*
|
1769 |
+
* @return float|bool
|
1770 |
+
*/
|
1771 |
public static function getFileSizeSyscall($path) {
|
1772 |
$filesize = false;
|
1773 |
|
1792 |
return $filesize;
|
1793 |
}
|
1794 |
|
1795 |
+
/**
|
1796 |
+
* @param string $filename
|
1797 |
+
*
|
1798 |
+
* @return string|false
|
1799 |
+
*/
|
1800 |
+
public static function truepath($filename) {
|
1801 |
+
// 2017-11-08: this could use some improvement, patches welcome
|
1802 |
+
if (preg_match('#^(\\\\\\\\|//)[a-z0-9]#i', $filename, $matches)) {
|
1803 |
+
// PHP's built-in realpath function does not work on UNC Windows shares
|
1804 |
+
$goodpath = array();
|
1805 |
+
foreach (explode('/', str_replace('\\', '/', $filename)) as $part) {
|
1806 |
+
if ($part == '.') {
|
1807 |
+
continue;
|
1808 |
+
}
|
1809 |
+
if ($part == '..') {
|
1810 |
+
if (count($goodpath)) {
|
1811 |
+
array_pop($goodpath);
|
1812 |
+
} else {
|
1813 |
+
// cannot step above this level, already at top level
|
1814 |
+
return false;
|
1815 |
+
}
|
1816 |
+
} else {
|
1817 |
+
$goodpath[] = $part;
|
1818 |
+
}
|
1819 |
+
}
|
1820 |
+
return implode(DIRECTORY_SEPARATOR, $goodpath);
|
1821 |
+
}
|
1822 |
+
return realpath($filename);
|
1823 |
+
}
|
1824 |
|
1825 |
/**
|
1826 |
+
* Workaround for Bug #37268 (https://bugs.php.net/bug.php?id=37268)
|
1827 |
+
*
|
1828 |
+
* @param string $path A path.
|
1829 |
+
* @param string $suffix If the name component ends in suffix this will also be cut off.
|
1830 |
+
*
|
1831 |
+
* @return string
|
1832 |
+
*/
|
1833 |
public static function mb_basename($path, $suffix = null) {
|
1834 |
$splited = preg_split('#/#', rtrim($path, '/ '));
|
1835 |
return substr(basename('X'.$splited[count($splited) - 1], $suffix), 1);
|
lib/getid3/getid3.php
CHANGED
@@ -1,10 +1,9 @@
|
|
1 |
<?php
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
/////////////////////////////////////////////////////////////////
|
8 |
// //
|
9 |
// Please see readme.txt for more information //
|
10 |
// ///
|
@@ -22,6 +21,17 @@ if (!defined('GETID3_INCLUDEPATH')) {
|
|
22 |
if (!defined('IMG_JPG') && defined('IMAGETYPE_JPEG')) {
|
23 |
define('IMG_JPG', IMAGETYPE_JPEG);
|
24 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
|
26 |
// attempt to define temp dir as something flexible but reliable
|
27 |
$temp_dir = ini_get('upload_tmp_dir');
|
@@ -68,253 +78,410 @@ unset($open_basedir, $temp_dir);
|
|
68 |
|
69 |
// End: Defines
|
70 |
|
71 |
-
// Do not proceed getID3 if already exist.
|
72 |
-
if ( class_exists ( "getID3" ) ) {
|
73 |
-
return;
|
74 |
-
}
|
75 |
-
|
76 |
-
if ( class_exists ( "getid3_exception" ) ) {
|
77 |
-
return;
|
78 |
-
}
|
79 |
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
|
160 |
-
|
161 |
-
|
162 |
-
|
|
|
|
|
|
|
163 |
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
}
|
169 |
}
|
|
|
170 |
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
}
|
176 |
}
|
|
|
177 |
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
|
187 |
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
}
|
216 |
}
|
217 |
}
|
218 |
-
} else {
|
219 |
-
$this->startup_warning .= 'GETID3_HELPERAPPSDIR must not have any spaces in it - use 8dot3 naming convention if neccesary. You can run "dir /x" from the commandline to see the correct 8.3-style names.';
|
220 |
}
|
|
|
|
|
221 |
}
|
222 |
-
$path_so_far[] = $value;
|
223 |
}
|
224 |
-
$
|
225 |
}
|
226 |
-
|
227 |
}
|
228 |
-
|
229 |
-
return true;
|
230 |
}
|
231 |
|
232 |
-
|
233 |
-
|
|
|
234 |
}
|
|
|
235 |
|
236 |
-
|
237 |
-
|
238 |
-
|
|
|
|
|
|
|
239 |
|
|
|
|
|
|
|
|
|
|
|
|
|
240 |
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
|
|
|
|
251 |
}
|
252 |
-
|
253 |
}
|
|
|
|
|
254 |
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
263 |
}
|
|
|
264 |
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
|
276 |
-
|
277 |
-
|
278 |
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
}
|
|
|
|
|
299 |
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
318 |
$real_filesize = getid3_lib::getFileSizeSyscall($this->info['filenamepath']);
|
319 |
|
320 |
if ($real_filesize === false) {
|
@@ -324,381 +491,402 @@ if( ! class_exists( 'getID3' ) ){
|
|
324 |
} elseif (getid3_lib::intValueSupported($real_filesize)) {
|
325 |
unset($this->info['filesize']);
|
326 |
fclose($this->fp);
|
327 |
-
throw new getid3_exception('PHP seems to think the file is larger than '.round(PHP_INT_MAX / 1073741824).'GB, but filesystem reports it as '.number_format($real_filesize, 3).'GB, please report to info@getid3.org');
|
328 |
}
|
329 |
$this->info['filesize'] = $real_filesize;
|
330 |
-
$this->warning('File is larger than '.round(PHP_INT_MAX / 1073741824).'GB (filesystem reports it as '.number_format($real_filesize, 3).'GB) and is not properly supported by PHP.');
|
331 |
-
}
|
332 |
}
|
333 |
-
|
334 |
-
// set more parameters
|
335 |
-
$this->info['avdataoffset'] = 0;
|
336 |
-
$this->info['avdataend'] = $this->info['filesize'];
|
337 |
-
$this->info['fileformat'] = ''; // filled in later
|
338 |
-
$this->info['audio']['dataformat'] = ''; // filled in later, unset if not used
|
339 |
-
$this->info['video']['dataformat'] = ''; // filled in later, unset if not used
|
340 |
-
$this->info['tags'] = array(); // filled in later, unset if not used
|
341 |
-
$this->info['error'] = array(); // filled in later, unset if not used
|
342 |
-
$this->info['warning'] = array(); // filled in later, unset if not used
|
343 |
-
$this->info['comments'] = array(); // filled in later, unset if not used
|
344 |
-
$this->info['encoding'] = $this->encoding; // required by id3v2 and iso modules - can be unset at the end if desired
|
345 |
-
|
346 |
-
return true;
|
347 |
-
|
348 |
-
} catch (Exception $e) {
|
349 |
-
$this->error($e->getMessage());
|
350 |
}
|
351 |
-
|
|
|
|
|
|
|
|
|
352 |
}
|
|
|
|
|
353 |
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
360 |
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
}
|
371 |
-
catch (getid3_exception $e) {
|
372 |
-
throw $e;
|
373 |
-
}
|
374 |
}
|
375 |
-
|
376 |
-
|
377 |
-
$this->info['avdataoffset'] = max($this->info['avdataoffset'], $this->info['id3v2']['tag_offset_end']);
|
378 |
-
}
|
379 |
-
foreach (array('id3v1'=>'id3v1', 'apetag'=>'ape', 'lyrics3'=>'lyrics3') as $tag_name => $tag_key) {
|
380 |
-
if (isset($this->info[$tag_key]['tag_offset_start'])) {
|
381 |
-
$this->info['avdataend'] = min($this->info['avdataend'], $this->info[$tag_key]['tag_offset_start']);
|
382 |
}
|
383 |
}
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
$this->info['id3v2']['majorversion'] = ord($header{3});
|
392 |
-
$this->info['id3v2']['minorversion'] = ord($header{4});
|
393 |
-
$this->info['avdataoffset'] += getid3_lib::BigEndian2Int(substr($header, 6, 4), 1) + 10; // length of ID3v2 tag in 10-byte header doesn't include 10-byte header length
|
394 |
-
}
|
395 |
}
|
|
|
396 |
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
fclose($this->fp);
|
407 |
-
return $this->error('unable to determine file format');
|
408 |
}
|
|
|
409 |
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
fclose($this->fp);
|
414 |
-
return $this->error('ID3 tags not allowed on this file type.');
|
415 |
-
} elseif ($determined_format['fail_id3'] === 'WARNING') {
|
416 |
-
$this->warning('ID3 tags not allowed on this file type.');
|
417 |
-
}
|
418 |
-
}
|
419 |
|
420 |
-
|
421 |
-
|
422 |
-
if ($determined_format['fail_ape'] === 'ERROR') {
|
423 |
-
fclose($this->fp);
|
424 |
-
return $this->error('APE tags not allowed on this file type.');
|
425 |
-
} elseif ($determined_format['fail_ape'] === 'WARNING') {
|
426 |
-
$this->warning('APE tags not allowed on this file type.');
|
427 |
-
}
|
428 |
-
}
|
429 |
|
430 |
-
|
431 |
-
|
|
|
|
|
|
|
432 |
|
433 |
-
|
434 |
-
|
|
|
435 |
fclose($this->fp);
|
436 |
-
return $this->error('
|
|
|
|
|
437 |
}
|
|
|
438 |
|
439 |
-
|
440 |
-
|
441 |
-
if (
|
442 |
-
$
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
$errormessage .= 'PHP is not compiled with iconv() support. Please recompile with the --with-iconv switch';
|
447 |
-
}
|
448 |
-
return $this->error($errormessage);
|
449 |
}
|
|
|
450 |
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
// instantiate module class
|
455 |
-
$class_name = 'getid3_'.$determined_format['module'];
|
456 |
-
if (!class_exists($class_name)) {
|
457 |
-
return $this->error('Format not supported, module "'.$determined_format['include'].'" is corrupt.');
|
458 |
-
}
|
459 |
-
$class = new $class_name($this);
|
460 |
-
$class->Analyze();
|
461 |
-
unset($class);
|
462 |
|
463 |
-
|
|
|
464 |
fclose($this->fp);
|
|
|
|
|
465 |
|
466 |
-
|
467 |
-
|
468 |
-
|
|
|
|
|
|
|
|
|
|
|
469 |
}
|
|
|
|
|
470 |
|
471 |
-
|
472 |
-
|
473 |
-
$this->ChannelsBitratePlaytimeCalculations();
|
474 |
-
$this->CalculateCompressionRatioVideo();
|
475 |
-
$this->CalculateCompressionRatioAudio();
|
476 |
-
$this->CalculateReplayGain();
|
477 |
-
$this->ProcessAudioStreams();
|
478 |
-
}
|
479 |
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
|
|
487 |
|
488 |
-
|
489 |
-
|
490 |
-
$this->getHashdata('sha1');
|
491 |
-
}
|
492 |
|
493 |
-
|
494 |
-
|
|
|
|
|
495 |
|
496 |
-
|
497 |
-
|
|
|
|
|
|
|
|
|
|
|
498 |
}
|
499 |
|
500 |
-
//
|
501 |
-
|
502 |
-
|
|
|
|
|
|
|
|
|
503 |
|
|
|
|
|
|
|
|
|
504 |
|
505 |
-
|
506 |
-
public function error($message) {
|
507 |
$this->CleanUp();
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
$this->info['error'][] = $message;
|
512 |
-
return $this->info;
|
513 |
}
|
514 |
|
|
|
|
|
|
|
515 |
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
520 |
}
|
|
|
|
|
|
|
521 |
|
522 |
|
523 |
-
|
524 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
525 |
|
526 |
-
// remove possible empty keys
|
527 |
-
$AVpossibleEmptyKeys = array('dataformat', 'bits_per_sample', 'encoder_options', 'streams', 'bitrate');
|
528 |
-
foreach ($AVpossibleEmptyKeys as $dummy => $key) {
|
529 |
-
if (empty($this->info['audio'][$key]) && isset($this->info['audio'][$key])) {
|
530 |
-
unset($this->info['audio'][$key]);
|
531 |
-
}
|
532 |
-
if (empty($this->info['video'][$key]) && isset($this->info['video'][$key])) {
|
533 |
-
unset($this->info['video'][$key]);
|
534 |
-
}
|
535 |
-
}
|
536 |
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
544 |
}
|
|
|
545 |
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
if (isset($this->info['avdataend'])) {
|
552 |
-
unset($this->info['avdataend']);
|
553 |
}
|
554 |
}
|
|
|
555 |
|
556 |
-
|
557 |
-
|
558 |
-
|
|
|
559 |
}
|
560 |
-
if (
|
561 |
-
|
562 |
}
|
|
|
563 |
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
return true;
|
568 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
569 |
|
|
|
|
|
570 |
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
702 |
|
703 |
// has been known to produce false matches in random files (e.g. JPEGs), leave out until more precise matching available
|
704 |
// // MOD - audio - MODule (assorted sub-formats)
|
@@ -710,1132 +898,1280 @@ if( ! class_exists( 'getID3' ) ){
|
|
710 |
// 'mime_type' => 'audio/mod',
|
711 |
// ),
|
712 |
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
|
809 |
-
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
|
816 |
-
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
-
|
821 |
-
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
|
837 |
-
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
853 |
-
|
854 |
-
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
864 |
-
|
865 |
-
|
866 |
-
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
877 |
-
|
878 |
-
|
879 |
-
|
880 |
-
|
881 |
-
|
882 |
-
|
883 |
-
|
884 |
-
|
885 |
-
|
886 |
-
|
887 |
-
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
-
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
-
|
899 |
-
|
900 |
-
|
901 |
-
|
902 |
-
|
903 |
-
|
904 |
-
|
905 |
-
|
906 |
-
|
907 |
-
|
908 |
-
|
909 |
-
|
910 |
-
|
911 |
-
|
912 |
-
|
913 |
-
|
914 |
-
|
915 |
-
|
916 |
-
|
917 |
-
|
918 |
-
|
919 |
-
|
920 |
-
|
921 |
-
|
922 |
-
|
923 |
-
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
-
|
928 |
-
|
929 |
-
|
930 |
-
|
931 |
-
|
932 |
-
|
933 |
-
|
934 |
-
|
935 |
-
|
936 |
-
|
937 |
-
|
938 |
-
|
939 |
-
|
940 |
-
|
941 |
-
|
942 |
-
|
943 |
-
|
944 |
-
|
945 |
-
|
946 |
-
|
947 |
-
|
948 |
-
|
949 |
-
|
950 |
-
|
951 |
-
|
952 |
-
|
953 |
-
|
954 |
-
|
955 |
-
|
956 |
-
|
957 |
-
|
958 |
-
|
959 |
-
|
960 |
-
|
961 |
-
|
962 |
-
|
963 |
-
|
964 |
-
|
965 |
-
|
966 |
-
|
967 |
-
|
968 |
-
|
969 |
-
|
970 |
-
|
971 |
-
|
972 |
-
|
973 |
-
|
974 |
-
|
975 |
-
|
976 |
-
|
977 |
-
|
978 |
-
|
979 |
-
|
980 |
-
|
981 |
-
|
982 |
-
|
983 |
-
|
984 |
-
|
985 |
-
|
986 |
-
|
987 |
-
|
988 |
-
|
989 |
-
|
990 |
-
|
991 |
-
|
992 |
-
|
993 |
-
|
994 |
-
|
995 |
-
|
996 |
-
|
997 |
-
|
998 |
-
|
999 |
-
|
1000 |
-
|
1001 |
-
|
1002 |
-
|
1003 |
-
|
1004 |
-
|
1005 |
-
|
1006 |
-
|
1007 |
-
|
1008 |
-
|
1009 |
-
|
1010 |
-
|
1011 |
-
|
1012 |
-
|
1013 |
-
|
1014 |
-
|
1015 |
-
|
1016 |
-
|
1017 |
-
|
1018 |
-
|
1019 |
-
|
1020 |
-
|
1021 |
-
|
1022 |
-
|
1023 |
-
|
1024 |
-
|
1025 |
-
|
1026 |
-
|
1027 |
-
|
1028 |
-
|
1029 |
-
|
1030 |
-
|
1031 |
-
|
1032 |
-
|
1033 |
-
|
1034 |
-
|
1035 |
-
|
1036 |
-
|
1037 |
-
|
1038 |
-
|
1039 |
-
|
1040 |
-
|
1041 |
-
|
1042 |
-
|
1043 |
-
|
1044 |
-
|
1045 |
-
|
1046 |
-
|
1047 |
-
|
1048 |
-
|
1049 |
-
|
1050 |
-
|
1051 |
-
|
1052 |
-
|
1053 |
-
|
1054 |
-
|
1055 |
-
|
1056 |
-
|
1057 |
-
|
1058 |
-
|
1059 |
-
|
1060 |
-
|
1061 |
-
|
1062 |
-
|
1063 |
-
|
1064 |
-
|
1065 |
-
|
1066 |
-
|
1067 |
-
|
1068 |
-
|
1069 |
-
|
1070 |
-
|
1071 |
-
|
1072 |
-
|
1073 |
-
|
1074 |
-
|
1075 |
-
|
1076 |
-
|
1077 |
-
|
1078 |
-
|
1079 |
-
|
1080 |
-
|
1081 |
-
|
1082 |
-
|
1083 |
-
|
1084 |
-
|
1085 |
-
|
1086 |
-
|
1087 |
-
|
1088 |
-
|
1089 |
-
|
1090 |
-
|
1091 |
-
|
1092 |
-
|
1093 |
-
|
1094 |
-
|
1095 |
-
|
1096 |
-
|
1097 |
-
|
1098 |
-
|
1099 |
-
|
1100 |
-
|
1101 |
-
|
1102 |
-
|
1103 |
-
|
1104 |
-
|
1105 |
-
|
1106 |
-
|
1107 |
-
|
1108 |
-
|
1109 |
-
|
1110 |
-
|
1111 |
-
|
1112 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1113 |
}
|
1114 |
|
|
|
|
|
1115 |
|
1116 |
-
|
1117 |
-
|
1118 |
-
|
1119 |
-
|
1120 |
-
|
1121 |
-
|
1122 |
-
|
1123 |
-
|
1124 |
-
|
1125 |
-
|
1126 |
-
|
1127 |
-
|
1128 |
-
|
1129 |
-
|
1130 |
-
|
1131 |
-
|
1132 |
-
|
1133 |
-
|
1134 |
-
if (preg_match('#\.mp[123a]$#i', $filename)) {
|
1135 |
-
// Too many mp3 encoders on the market put gabage in front of mpeg files
|
1136 |
-
// use assume format on these if format detection failed
|
1137 |
-
$GetFileFormatArray = $this->GetFileFormatArray();
|
1138 |
-
$info = $GetFileFormatArray['mp3'];
|
1139 |
$info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php';
|
1140 |
return $info;
|
1141 |
-
} elseif (preg_match('/\.cue$/i', $filename) && preg_match('#FILE "[^"]+" (BINARY|MOTOROLA|AIFF|WAVE|MP3)#', $filedata)) {
|
1142 |
-
// there's not really a useful consistent "magic" at the beginning of .cue files to identify them
|
1143 |
-
// so until I think of something better, just go by filename if all other format checks fail
|
1144 |
-
// and verify there's at least one instance of "TRACK xx AUDIO" in the file
|
1145 |
-
$GetFileFormatArray = $this->GetFileFormatArray();
|
1146 |
-
$info = $GetFileFormatArray['cue'];
|
1147 |
-
$info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php';
|
1148 |
-
return $info;
|
1149 |
}
|
1150 |
-
|
1151 |
-
return false;
|
1152 |
}
|
1153 |
|
1154 |
|
1155 |
-
|
1156 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1157 |
|
1158 |
-
|
1159 |
-
|
1160 |
-
return;
|
1161 |
-
}
|
1162 |
|
1163 |
-
|
1164 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1165 |
|
1166 |
-
|
1167 |
-
|
1168 |
-
$this->CharConvert($array[$key], $encoding);
|
1169 |
-
}
|
1170 |
|
1171 |
-
|
1172 |
-
|
1173 |
-
|
1174 |
-
}
|
1175 |
}
|
1176 |
-
}
|
1177 |
|
1178 |
-
|
1179 |
-
|
1180 |
-
|
1181 |
-
// key name => array (tag name, character encoding)
|
1182 |
-
static $tags;
|
1183 |
-
if (empty($tags)) {
|
1184 |
-
$tags = array(
|
1185 |
-
'asf' => array('asf' , 'UTF-16LE'),
|
1186 |
-
'midi' => array('midi' , 'ISO-8859-1'),
|
1187 |
-
'nsv' => array('nsv' , 'ISO-8859-1'),
|
1188 |
-
'ogg' => array('vorbiscomment' , 'UTF-8'),
|
1189 |
-
'png' => array('png' , 'UTF-8'),
|
1190 |
-
'tiff' => array('tiff' , 'ISO-8859-1'),
|
1191 |
-
'quicktime' => array('quicktime' , 'UTF-8'),
|
1192 |
-
'real' => array('real' , 'ISO-8859-1'),
|
1193 |
-
'vqf' => array('vqf' , 'ISO-8859-1'),
|
1194 |
-
'zip' => array('zip' , 'ISO-8859-1'),
|
1195 |
-
'riff' => array('riff' , 'ISO-8859-1'),
|
1196 |
-
'lyrics3' => array('lyrics3' , 'ISO-8859-1'),
|
1197 |
-
'id3v1' => array('id3v1' , $this->encoding_id3v1),
|
1198 |
-
'id3v2' => array('id3v2' , 'UTF-8'), // not according to the specs (every frame can have a different encoding), but getID3() force-converts all encodings to UTF-8
|
1199 |
-
'ape' => array('ape' , 'UTF-8'),
|
1200 |
-
'cue' => array('cue' , 'ISO-8859-1'),
|
1201 |
-
'matroska' => array('matroska' , 'UTF-8'),
|
1202 |
-
'flac' => array('vorbiscomment' , 'UTF-8'),
|
1203 |
-
'divxtag' => array('divx' , 'ISO-8859-1'),
|
1204 |
-
'iptc' => array('iptc' , 'ISO-8859-1'),
|
1205 |
-
);
|
1206 |
}
|
|
|
|
|
1207 |
|
1208 |
-
|
1209 |
-
|
1210 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1211 |
|
1212 |
-
|
1213 |
-
|
1214 |
-
|
1215 |
-
}
|
1216 |
|
1217 |
-
|
1218 |
-
|
1219 |
-
|
1220 |
-
|
1221 |
-
|
1222 |
-
|
1223 |
-
|
1224 |
-
|
1225 |
-
|
1226 |
-
|
1227 |
-
|
1228 |
-
$this->info['tags'][trim($tag_name)][trim($tag_key)][] = $value;
|
1229 |
-
}
|
1230 |
-
}
|
1231 |
}
|
1232 |
-
if ($
|
1233 |
-
|
|
|
|
|
|
|
|
|
1234 |
}
|
1235 |
}
|
1236 |
-
|
1237 |
-
|
1238 |
-
|
1239 |
-
continue;
|
1240 |
}
|
|
|
1241 |
|
1242 |
-
|
1243 |
-
|
1244 |
-
|
1245 |
-
|
1246 |
-
}
|
1247 |
|
1248 |
-
|
1249 |
-
|
1250 |
-
|
1251 |
-
|
1252 |
-
if ($
|
1253 |
-
|
1254 |
-
|
1255 |
-
|
1256 |
-
if (preg_match('#^[\\x80-\\xFF]+$#', $value)) {
|
1257 |
-
foreach (array('windows-1251', 'KOI8-R') as $id3v1_bad_encoding) {
|
1258 |
-
if (@iconv($id3v1_bad_encoding, $id3v1_bad_encoding, $value) === $value) {
|
1259 |
-
$encoding = $id3v1_bad_encoding;
|
1260 |
-
break 3;
|
1261 |
-
}
|
1262 |
-
}
|
1263 |
-
}
|
1264 |
-
}
|
1265 |
-
}
|
1266 |
-
}
|
1267 |
}
|
|
|
1268 |
}
|
1269 |
-
// ID3v1 encoding detection hack end
|
1270 |
-
|
1271 |
-
$this->CharConvert($this->info['tags'][$tag_name], $encoding); // only copy gets converted!
|
1272 |
}
|
1273 |
|
1274 |
}
|
1275 |
|
1276 |
-
|
1277 |
-
|
1278 |
-
|
1279 |
-
|
1280 |
-
|
1281 |
-
|
1282 |
-
|
1283 |
-
|
1284 |
-
|
1285 |
-
|
1286 |
-
|
1287 |
-
|
1288 |
-
|
1289 |
-
|
1290 |
-
|
1291 |
-
|
1292 |
}
|
1293 |
}
|
1294 |
}
|
1295 |
}
|
1296 |
-
|
1297 |
-
|
1298 |
-
|
1299 |
-
|
1300 |
-
|
1301 |
-
if (empty($this->info[$unset_key][$tagtype])) {
|
1302 |
-
unset($this->info[$unset_key][$tagtype]);
|
1303 |
-
}
|
1304 |
-
if (empty($this->info[$unset_key])) {
|
1305 |
-
unset($this->info[$unset_key]);
|
1306 |
-
}
|
1307 |
-
}
|
1308 |
-
// remove duplicate copy of picture data from (e.g. [id3v2][comments][picture])
|
1309 |
-
if (isset($this->info[$tagtype]['comments']['picture'])) {
|
1310 |
-
unset($this->info[$tagtype]['comments']['picture']);
|
1311 |
}
|
1312 |
-
if (empty($this->info[$
|
1313 |
-
unset($this->info[$
|
1314 |
}
|
1315 |
-
if (empty($this->info[$
|
1316 |
-
unset($this->info[$
|
1317 |
}
|
1318 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1319 |
}
|
1320 |
-
return true;
|
1321 |
}
|
|
|
|
|
1322 |
|
1323 |
-
|
1324 |
-
|
1325 |
-
|
1326 |
-
|
1327 |
-
|
1328 |
-
|
1329 |
-
|
1330 |
-
|
1331 |
-
|
1332 |
-
|
1333 |
-
|
1334 |
-
|
1335 |
-
|
1336 |
-
|
1337 |
-
|
1338 |
-
// comments) using the normal getID3() method of MD5'ing the data between the
|
1339 |
-
// end of the comments and the end of the file (minus any trailing tags),
|
1340 |
-
// because the page sequence numbers of the pages that the audio data is on
|
1341 |
-
// do not match. Under normal circumstances, where comments are smaller than
|
1342 |
-
// the nominal 4-8kB page size, then this is not a problem, but if there are
|
1343 |
-
// very large comments, the only way around it is to strip off the comment
|
1344 |
-
// tags with vorbiscomment and MD5 that file.
|
1345 |
-
// This procedure must be applied to ALL Ogg files, not just the ones with
|
1346 |
-
// comments larger than 1 page, because the below method simply MD5's the
|
1347 |
-
// whole file with the comments stripped, not just the portion after the
|
1348 |
-
// comments block (which is the standard getID3() method.
|
1349 |
-
|
1350 |
-
// The above-mentioned problem of comments spanning multiple pages and changing
|
1351 |
-
// page sequence numbers likely happens for OggSpeex and OggFLAC as well, but
|
1352 |
-
// currently vorbiscomment only works on OggVorbis files.
|
1353 |
-
|
1354 |
-
if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) {
|
1355 |
-
|
1356 |
-
$this->warning('Failed making system call to vorbiscomment.exe - '.$algorithm.'_data is incorrect - error returned: PHP running in Safe Mode (backtick operator not available)');
|
1357 |
-
$this->info[$algorithm.'_data'] = false;
|
1358 |
-
|
1359 |
-
} else {
|
1360 |
-
|
1361 |
-
// Prevent user from aborting script
|
1362 |
-
$old_abort = ignore_user_abort(true);
|
1363 |
|
1364 |
-
|
1365 |
-
|
1366 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1367 |
|
1368 |
-
|
1369 |
-
$temp = tempnam(GETID3_TEMP_DIR, 'getID3');
|
1370 |
-
$file = $this->info['filenamepath'];
|
1371 |
|
1372 |
-
|
|
|
1373 |
|
1374 |
-
|
1375 |
|
1376 |
-
|
1377 |
-
|
1378 |
|
1379 |
-
|
|
|
|
|
1380 |
|
1381 |
-
|
|
|
|
|
1382 |
|
1383 |
-
|
1384 |
|
1385 |
-
|
1386 |
|
1387 |
-
$commandline = 'vorbiscomment -w -c "'.$empty.'" "'.$file.'" "'.$temp.'"
|
1388 |
-
$commandline = 'vorbiscomment -w -c '.escapeshellarg($empty).' '.escapeshellarg($file).' '.escapeshellarg($temp).' 2>&1';
|
1389 |
$VorbisCommentError = `$commandline`;
|
1390 |
|
1391 |
-
}
|
1392 |
-
|
1393 |
-
if (!empty($VorbisCommentError)) {
|
1394 |
-
|
1395 |
-
$this->info['warning'][] = 'Failed making system call to vorbiscomment(.exe) - '.$algorithm.'_data will be incorrect. If vorbiscomment is unavailable, please download from http://www.vorbis.com/download.psp and put in the getID3() directory. Error returned: '.$VorbisCommentError;
|
1396 |
-
$this->info[$algorithm.'_data'] = false;
|
1397 |
-
|
1398 |
} else {
|
1399 |
|
1400 |
-
|
1401 |
-
switch ($algorithm) {
|
1402 |
-
case 'md5':
|
1403 |
-
$this->info[$algorithm.'_data'] = md5_file($temp);
|
1404 |
-
break;
|
1405 |
|
1406 |
-
case 'sha1':
|
1407 |
-
$this->info[$algorithm.'_data'] = sha1_file($temp);
|
1408 |
-
break;
|
1409 |
-
}
|
1410 |
}
|
1411 |
|
1412 |
-
|
1413 |
-
unlink($empty);
|
1414 |
-
unlink($temp);
|
1415 |
|
1416 |
-
|
1417 |
-
|
1418 |
|
1419 |
}
|
1420 |
|
1421 |
-
|
1422 |
-
|
1423 |
-
if (!empty($this->info['avdataoffset']) || (isset($this->info['avdataend']) && ($this->info['avdataend'] < $this->info['filesize']))) {
|
1424 |
|
1425 |
-
|
1426 |
-
$this->info[$algorithm.'_data'] =
|
1427 |
|
1428 |
} else {
|
1429 |
|
1430 |
-
//
|
1431 |
switch ($algorithm) {
|
1432 |
case 'md5':
|
1433 |
-
$this->info[$algorithm.'_data'] = md5_file($
|
1434 |
break;
|
1435 |
|
1436 |
case 'sha1':
|
1437 |
-
$this->info[$algorithm.'_data'] = sha1_file($
|
1438 |
break;
|
1439 |
}
|
1440 |
}
|
1441 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1442 |
}
|
1443 |
-
return true;
|
1444 |
-
}
|
1445 |
|
|
|
1446 |
|
1447 |
-
|
1448 |
|
1449 |
-
|
1450 |
-
|
1451 |
-
// ignore
|
1452 |
-
} elseif ($this->info['audio']['channels'] == 1) {
|
1453 |
-
$this->info['audio']['channelmode'] = 'mono';
|
1454 |
-
} elseif ($this->info['audio']['channels'] == 2) {
|
1455 |
-
$this->info['audio']['channelmode'] = 'stereo';
|
1456 |
-
}
|
1457 |
|
1458 |
-
|
1459 |
-
$CombinedBitrate = 0;
|
1460 |
-
$CombinedBitrate += (isset($this->info['audio']['bitrate']) ? $this->info['audio']['bitrate'] : 0);
|
1461 |
-
$CombinedBitrate += (isset($this->info['video']['bitrate']) ? $this->info['video']['bitrate'] : 0);
|
1462 |
-
if (($CombinedBitrate > 0) && empty($this->info['bitrate'])) {
|
1463 |
-
$this->info['bitrate'] = $CombinedBitrate;
|
1464 |
-
}
|
1465 |
-
//if ((isset($this->info['video']) && !isset($this->info['video']['bitrate'])) || (isset($this->info['audio']) && !isset($this->info['audio']['bitrate']))) {
|
1466 |
-
// // for example, VBR MPEG video files cannot determine video bitrate:
|
1467 |
-
// // should not set overall bitrate and playtime from audio bitrate only
|
1468 |
-
// unset($this->info['bitrate']);
|
1469 |
-
//}
|
1470 |
-
|
1471 |
-
// video bitrate undetermined, but calculable
|
1472 |
-
if (isset($this->info['video']['dataformat']) && $this->info['video']['dataformat'] && (!isset($this->info['video']['bitrate']) || ($this->info['video']['bitrate'] == 0))) {
|
1473 |
-
// if video bitrate not set
|
1474 |
-
if (isset($this->info['audio']['bitrate']) && ($this->info['audio']['bitrate'] > 0) && ($this->info['audio']['bitrate'] == $this->info['bitrate'])) {
|
1475 |
-
// AND if audio bitrate is set to same as overall bitrate
|
1476 |
-
if (isset($this->info['playtime_seconds']) && ($this->info['playtime_seconds'] > 0)) {
|
1477 |
-
// AND if playtime is set
|
1478 |
-
if (isset($this->info['avdataend']) && isset($this->info['avdataoffset'])) {
|
1479 |
-
// AND if AV data offset start/end is known
|
1480 |
-
// THEN we can calculate the video bitrate
|
1481 |
-
$this->info['bitrate'] = round((($this->info['avdataend'] - $this->info['avdataoffset']) * 8) / $this->info['playtime_seconds']);
|
1482 |
-
$this->info['video']['bitrate'] = $this->info['bitrate'] - $this->info['audio']['bitrate'];
|
1483 |
-
}
|
1484 |
-
}
|
1485 |
-
}
|
1486 |
-
}
|
1487 |
|
1488 |
-
|
1489 |
-
|
1490 |
-
|
|
|
|
|
1491 |
|
1492 |
-
|
1493 |
-
|
1494 |
-
|
1495 |
-
if (isset($this->info['bitrate']) && empty($this->info['audio']['bitrate']) && empty($this->info['video']['bitrate'])) {
|
1496 |
-
if (isset($this->info['audio']['dataformat']) && empty($this->info['video']['resolution_x'])) {
|
1497 |
-
// audio only
|
1498 |
-
$this->info['audio']['bitrate'] = $this->info['bitrate'];
|
1499 |
-
} elseif (isset($this->info['video']['resolution_x']) && empty($this->info['audio']['dataformat'])) {
|
1500 |
-
// video only
|
1501 |
-
$this->info['video']['bitrate'] = $this->info['bitrate'];
|
1502 |
}
|
1503 |
}
|
1504 |
|
1505 |
-
// Set playtime string
|
1506 |
-
if (!empty($this->info['playtime_seconds']) && empty($this->info['playtime_string'])) {
|
1507 |
-
$this->info['playtime_string'] = getid3_lib::PlaytimeString($this->info['playtime_seconds']);
|
1508 |
-
}
|
1509 |
}
|
|
|
|
|
1510 |
|
|
|
1511 |
|
1512 |
-
|
1513 |
-
|
1514 |
-
|
1515 |
-
|
1516 |
-
|
1517 |
-
|
1518 |
-
|
1519 |
-
|
1520 |
-
return false;
|
1521 |
-
}
|
1522 |
-
|
1523 |
-
switch ($this->info['video']['dataformat']) {
|
1524 |
-
case 'bmp':
|
1525 |
-
case 'gif':
|
1526 |
-
case 'jpeg':
|
1527 |
-
case 'jpg':
|
1528 |
-
case 'png':
|
1529 |
-
case 'tiff':
|
1530 |
-
$FrameRate = 1;
|
1531 |
-
$PlaytimeSeconds = 1;
|
1532 |
-
$BitrateCompressed = $this->info['filesize'] * 8;
|
1533 |
-
break;
|
1534 |
|
1535 |
-
|
1536 |
-
|
1537 |
-
|
1538 |
-
|
1539 |
-
|
1540 |
-
|
1541 |
-
|
1542 |
-
|
1543 |
-
|
1544 |
-
|
1545 |
-
|
1546 |
-
|
1547 |
-
|
1548 |
-
|
1549 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1550 |
}
|
1551 |
-
|
1552 |
}
|
1553 |
-
$BitrateUncompressed = $this->info['video']['resolution_x'] * $this->info['video']['resolution_y'] * $this->info['video']['bits_per_sample'] * $FrameRate;
|
1554 |
-
|
1555 |
-
$this->info['video']['compression_ratio'] = $BitrateCompressed / $BitrateUncompressed;
|
1556 |
-
return true;
|
1557 |
}
|
1558 |
|
|
|
|
|
|
|
1559 |
|
1560 |
-
|
1561 |
-
|
1562 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1563 |
}
|
1564 |
-
|
1565 |
|
1566 |
-
|
1567 |
-
|
1568 |
-
|
1569 |
-
$this->info['audio']['streams'][$streamnumber]['compression_ratio'] = $streamdata['bitrate'] / ($streamdata['channels'] * $streamdata['sample_rate'] * (!empty($streamdata['bits_per_sample']) ? $streamdata['bits_per_sample'] : 16));
|
1570 |
-
}
|
1571 |
-
}
|
1572 |
-
}
|
1573 |
-
return true;
|
1574 |
}
|
|
|
1575 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1576 |
|
1577 |
-
|
1578 |
-
|
1579 |
-
|
1580 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1581 |
}
|
1582 |
-
if (
|
1583 |
-
$
|
|
|
|
|
1584 |
}
|
1585 |
-
if (
|
1586 |
-
$
|
|
|
|
|
1587 |
}
|
|
|
|
|
|
|
1588 |
|
1589 |
-
|
1590 |
-
|
1591 |
-
|
1592 |
-
|
1593 |
-
|
1594 |
-
|
1595 |
-
|
1596 |
-
|
|
|
|
|
1597 |
}
|
|
|
1598 |
|
1599 |
-
|
1600 |
-
|
1601 |
-
if (!
|
1602 |
-
|
1603 |
-
if ($key != 'streams') {
|
1604 |
-
$this->info['audio']['streams'][0][$key] = $value;
|
1605 |
-
}
|
1606 |
-
}
|
1607 |
}
|
1608 |
}
|
1609 |
-
return true;
|
1610 |
}
|
|
|
|
|
1611 |
|
1612 |
-
|
1613 |
-
|
1614 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1615 |
|
1616 |
-
|
1617 |
-
|
1618 |
-
|
1619 |
-
|
|
|
1620 |
}
|
1621 |
-
include_once(GETID3_INCLUDEPATH.'module.'.$name.'.php');
|
1622 |
-
return true;
|
1623 |
}
|
1624 |
-
|
1625 |
}
|
1626 |
-
}
|
1627 |
-
|
1628 |
-
|
1629 |
-
if( ! class_exists( 'getid3_handler' ) ){
|
1630 |
-
abstract class getid3_handler {
|
1631 |
-
|
1632 |
-
/**
|
1633 |
-
* @var getID3
|
1634 |
-
*/
|
1635 |
-
protected $getid3; // pointer
|
1636 |
-
|
1637 |
-
protected $data_string_flag = false; // analyzing filepointer or string
|
1638 |
-
protected $data_string = ''; // string to analyze
|
1639 |
-
protected $data_string_position = 0; // seek position in string
|
1640 |
-
protected $data_string_length = 0; // string length
|
1641 |
-
|
1642 |
-
private $dependency_to = null;
|
1643 |
-
|
1644 |
|
1645 |
-
|
1646 |
-
|
1647 |
-
|
1648 |
-
|
1649 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
1650 |
}
|
1651 |
}
|
|
|
|
|
1652 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1653 |
|
1654 |
-
|
1655 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1656 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1657 |
|
1658 |
-
|
1659 |
-
public function AnalyzeString($string) {
|
1660 |
-
// Enter string mode
|
1661 |
-
$this->setStringMode($string);
|
1662 |
|
1663 |
-
// Save info
|
1664 |
-
$saved_avdataoffset = $this->getid3->info['avdataoffset'];
|
1665 |
-
$saved_avdataend = $this->getid3->info['avdataend'];
|
1666 |
-
$saved_filesize = (isset($this->getid3->info['filesize']) ? $this->getid3->info['filesize'] : null); // may be not set if called as dependency without openfile() call
|
1667 |
|
1668 |
-
|
1669 |
-
|
1670 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1671 |
|
1672 |
-
|
1673 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1674 |
|
1675 |
-
|
1676 |
-
|
1677 |
-
|
1678 |
-
|
|
|
|
|
|
|
|
|
1679 |
|
1680 |
-
|
1681 |
-
|
|
|
|
|
|
|
|
|
1682 |
}
|
|
|
|
|
1683 |
|
1684 |
-
|
1685 |
-
|
1686 |
-
|
1687 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1688 |
}
|
1689 |
-
|
1690 |
-
|
1691 |
-
|
1692 |
-
return $this->data_string_position;
|
1693 |
-
}
|
1694 |
-
return ftell($this->getid3->fp);
|
1695 |
}
|
1696 |
|
1697 |
-
|
1698 |
-
|
1699 |
-
|
1700 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1701 |
}
|
1702 |
-
$
|
1703 |
-
|
1704 |
-
|
1705 |
-
|
1706 |
-
|
1707 |
-
|
|
|
1708 |
|
1709 |
-
|
1710 |
-
|
1711 |
-
|
1712 |
-
|
1713 |
-
|
1714 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1715 |
|
1716 |
-
|
1717 |
-
|
1718 |
-
|
1719 |
|
1720 |
-
|
1721 |
-
|
1722 |
-
|
1723 |
-
}
|
1724 |
-
return 0;
|
1725 |
-
} else {
|
1726 |
-
$pos = $bytes;
|
1727 |
-
if ($whence == SEEK_CUR) {
|
1728 |
-
$pos = $this->ftell() + $bytes;
|
1729 |
-
} elseif ($whence == SEEK_END) {
|
1730 |
-
$pos = $this->getid3->info['filesize'] + $bytes;
|
1731 |
-
}
|
1732 |
-
if (!getid3_lib::intValueSupported($pos)) {
|
1733 |
-
throw new getid3_exception('cannot fseek('.$pos.') because beyond PHP filesystem limit', 10);
|
1734 |
-
}
|
1735 |
}
|
1736 |
-
return
|
1737 |
-
}
|
1738 |
-
|
1739 |
-
|
1740 |
-
|
1741 |
-
|
|
|
|
|
|
|
|
|
1742 |
}
|
1743 |
-
return feof($this->getid3->fp);
|
1744 |
-
}
|
1745 |
-
|
1746 |
-
final protected function isDependencyFor($module) {
|
1747 |
-
return $this->dependency_to == $module;
|
1748 |
-
}
|
1749 |
-
|
1750 |
-
protected function error($text) {
|
1751 |
-
$this->getid3->info['error'][] = $text;
|
1752 |
-
|
1753 |
-
return false;
|
1754 |
}
|
|
|
|
|
1755 |
|
1756 |
-
|
1757 |
-
|
|
|
|
|
|
|
|
|
1758 |
}
|
|
|
|
|
1759 |
|
1760 |
-
|
1761 |
-
|
1762 |
-
|
|
|
|
|
|
|
|
|
|
|
1763 |
|
1764 |
-
|
1765 |
-
|
|
|
|
|
|
|
|
|
|
|
1766 |
|
1767 |
-
|
1768 |
-
|
1769 |
|
1770 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1771 |
|
1772 |
-
|
1773 |
-
|
|
|
|
|
|
|
|
|
1774 |
|
1775 |
-
|
1776 |
-
|
1777 |
-
|
1778 |
-
|
1779 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1780 |
|
1781 |
-
|
1782 |
-
|
1783 |
|
1784 |
-
|
1785 |
-
|
1786 |
-
|
1787 |
-
|
1788 |
-
|
1789 |
-
|
1790 |
|
1791 |
-
|
1792 |
-
|
1793 |
-
|
1794 |
-
|
1795 |
|
1796 |
-
|
1797 |
-
|
1798 |
-
|
1799 |
-
|
1800 |
-
|
1801 |
-
|
1802 |
-
|
1803 |
-
}
|
1804 |
-
$bytesleft -= $byteswritten;
|
1805 |
}
|
1806 |
-
|
1807 |
-
fclose($fp_dest);
|
1808 |
-
$attachment = $dest;
|
1809 |
-
|
1810 |
}
|
1811 |
|
1812 |
-
|
|
|
1813 |
|
1814 |
-
|
1815 |
-
if (isset($fp_dest) && is_resource($fp_dest)) {
|
1816 |
-
fclose($fp_dest);
|
1817 |
-
unlink($dest);
|
1818 |
-
}
|
1819 |
|
1820 |
-
|
1821 |
-
$attachment = null;
|
1822 |
-
$this->warning('Failed to extract attachment '.$name.': '.$e->getMessage());
|
1823 |
|
|
|
|
|
|
|
1824 |
}
|
1825 |
|
1826 |
-
|
1827 |
-
|
|
|
|
|
|
|
|
|
|
|
1828 |
|
1829 |
-
return $attachment;
|
1830 |
}
|
1831 |
|
|
|
|
|
|
|
|
|
1832 |
}
|
|
|
1833 |
}
|
1834 |
|
1835 |
|
1836 |
-
|
1837 |
-
|
1838 |
-
|
1839 |
-
public $message;
|
1840 |
-
}
|
1841 |
}
|
1 |
<?php
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
5 |
+
// or https://www.getid3.org //
|
6 |
+
// or http://getid3.sourceforge.net //
|
|
|
7 |
// //
|
8 |
// Please see readme.txt for more information //
|
9 |
// ///
|
21 |
if (!defined('IMG_JPG') && defined('IMAGETYPE_JPEG')) {
|
22 |
define('IMG_JPG', IMAGETYPE_JPEG);
|
23 |
}
|
24 |
+
if (!defined('ENT_SUBSTITUTE')) { // PHP5.3 adds ENT_IGNORE, PHP5.4 adds ENT_SUBSTITUTE
|
25 |
+
define('ENT_SUBSTITUTE', (defined('ENT_IGNORE') ? ENT_IGNORE : 8));
|
26 |
+
}
|
27 |
+
|
28 |
+
/*
|
29 |
+
https://www.getid3.org/phpBB3/viewtopic.php?t=2114
|
30 |
+
If you are running into a the problem where filenames with special characters are being handled
|
31 |
+
incorrectly by external helper programs (e.g. metaflac), notably with the special characters removed,
|
32 |
+
and you are passing in the filename in UTF8 (typically via a HTML form), try uncommenting this line:
|
33 |
+
*/
|
34 |
+
//setlocale(LC_CTYPE, 'en_US.UTF-8');
|
35 |
|
36 |
// attempt to define temp dir as something flexible but reliable
|
37 |
$temp_dir = ini_get('upload_tmp_dir');
|
78 |
|
79 |
// End: Defines
|
80 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
|
82 |
+
class getID3
|
83 |
+
{
|
84 |
+
/*
|
85 |
+
* Settings
|
86 |
+
*/
|
87 |
+
|
88 |
+
/**
|
89 |
+
* CASE SENSITIVE! - i.e. (must be supported by iconv()). Examples: ISO-8859-1 UTF-8 UTF-16 UTF-16BE
|
90 |
+
*
|
91 |
+
* @var string
|
92 |
+
*/
|
93 |
+
public $encoding = 'UTF-8';
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Should always be 'ISO-8859-1', but some tags may be written in other encodings such as 'EUC-CN' or 'CP1252'
|
97 |
+
*
|
98 |
+
* @var string
|
99 |
+
*/
|
100 |
+
public $encoding_id3v1 = 'ISO-8859-1';
|
101 |
+
|
102 |
+
/*
|
103 |
+
* Optional tag checks - disable for speed.
|
104 |
+
*/
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Read and process ID3v1 tags
|
108 |
+
*
|
109 |
+
* @var bool
|
110 |
+
*/
|
111 |
+
public $option_tag_id3v1 = true;
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Read and process ID3v2 tags
|
115 |
+
*
|
116 |
+
* @var bool
|
117 |
+
*/
|
118 |
+
public $option_tag_id3v2 = true;
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Read and process Lyrics3 tags
|
122 |
+
*
|
123 |
+
* @var bool
|
124 |
+
*/
|
125 |
+
public $option_tag_lyrics3 = true;
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Read and process APE tags
|
129 |
+
*
|
130 |
+
* @var bool
|
131 |
+
*/
|
132 |
+
public $option_tag_apetag = true;
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Copy tags to root key 'tags' and encode to $this->encoding
|
136 |
+
*
|
137 |
+
* @var bool
|
138 |
+
*/
|
139 |
+
public $option_tags_process = true;
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Copy tags to root key 'tags_html' properly translated from various encodings to HTML entities
|
143 |
+
*
|
144 |
+
* @var bool
|
145 |
+
*/
|
146 |
+
public $option_tags_html = true;
|
147 |
+
|
148 |
+
/*
|
149 |
+
* Optional tag/comment calculations
|
150 |
+
*/
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Calculate additional info such as bitrate, channelmode etc
|
154 |
+
*
|
155 |
+
* @var bool
|
156 |
+
*/
|
157 |
+
public $option_extra_info = true;
|
158 |
+
|
159 |
+
/*
|
160 |
+
* Optional handling of embedded attachments (e.g. images)
|
161 |
+
*/
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Defaults to true (ATTACHMENTS_INLINE) for backward compatibility
|
165 |
+
*
|
166 |
+
* @var bool|string
|
167 |
+
*/
|
168 |
+
public $option_save_attachments = true;
|
169 |
+
|
170 |
+
/*
|
171 |
+
* Optional calculations
|
172 |
+
*/
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Get MD5 sum of data part - slow
|
176 |
+
*
|
177 |
+
* @var bool
|
178 |
+
*/
|
179 |
+
public $option_md5_data = false;
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Use MD5 of source file if availble - only FLAC and OptimFROG
|
183 |
+
*
|
184 |
+
* @var bool
|
185 |
+
*/
|
186 |
+
public $option_md5_data_source = false;
|
187 |
+
|
188 |
+
/**
|
189 |
+
* Get SHA1 sum of data part - slow
|
190 |
+
*
|
191 |
+
* @var bool
|
192 |
+
*/
|
193 |
+
public $option_sha1_data = false;
|
194 |
+
|
195 |
+
/**
|
196 |
+
* Check whether file is larger than 2GB and thus not supported by 32-bit PHP (null: auto-detect based on
|
197 |
+
* PHP_INT_MAX)
|
198 |
+
*
|
199 |
+
* @var bool|null
|
200 |
+
*/
|
201 |
+
public $option_max_2gb_check;
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Read buffer size in bytes
|
205 |
+
*
|
206 |
+
* @var int
|
207 |
+
*/
|
208 |
+
public $option_fread_buffer_size = 32768;
|
209 |
+
|
210 |
+
// Public variables
|
211 |
+
|
212 |
+
/**
|
213 |
+
* Filename of file being analysed.
|
214 |
+
*
|
215 |
+
* @var string
|
216 |
+
*/
|
217 |
+
public $filename;
|
218 |
+
|
219 |
+
/**
|
220 |
+
* Filepointer to file being analysed.
|
221 |
+
*
|
222 |
+
* @var resource
|
223 |
+
*/
|
224 |
+
public $fp;
|
225 |
+
|
226 |
+
/**
|
227 |
+
* Result array.
|
228 |
+
*
|
229 |
+
* @var array
|
230 |
+
*/
|
231 |
+
public $info;
|
232 |
+
|
233 |
+
/**
|
234 |
+
* @var string
|
235 |
+
*/
|
236 |
+
public $tempdir = GETID3_TEMP_DIR;
|
237 |
+
|
238 |
+
/**
|
239 |
+
* @var int
|
240 |
+
*/
|
241 |
+
public $memory_limit = 0;
|
242 |
+
|
243 |
+
/**
|
244 |
+
* @var string
|
245 |
+
*/
|
246 |
+
protected $startup_error = '';
|
247 |
+
|
248 |
+
/**
|
249 |
+
* @var string
|
250 |
+
*/
|
251 |
+
protected $startup_warning = '';
|
252 |
+
|
253 |
+
const VERSION = '1.9.17-201902071234';
|
254 |
+
const FREAD_BUFFER_SIZE = 32768;
|
255 |
+
|
256 |
+
const ATTACHMENTS_NONE = false;
|
257 |
+
const ATTACHMENTS_INLINE = true;
|
258 |
+
|
259 |
+
public function __construct() {
|
260 |
+
|
261 |
+
// Check for PHP version
|
262 |
+
$required_php_version = '5.3.0';
|
263 |
+
if (version_compare(PHP_VERSION, $required_php_version, '<')) {
|
264 |
+
$this->startup_error .= 'getID3() requires PHP v'.$required_php_version.' or higher - you are running v'.PHP_VERSION."\n";
|
265 |
+
return;
|
266 |
+
}
|
267 |
|
268 |
+
// Check memory
|
269 |
+
$this->memory_limit = ini_get('memory_limit');
|
270 |
+
if (preg_match('#([0-9]+) ?M#i', $this->memory_limit, $matches)) {
|
271 |
+
// could be stored as "16M" rather than 16777216 for example
|
272 |
+
$this->memory_limit = $matches[1] * 1048576;
|
273 |
+
} elseif (preg_match('#([0-9]+) ?G#i', $this->memory_limit, $matches)) { // The 'G' modifier is available since PHP 5.1.0
|
274 |
+
// could be stored as "2G" rather than 2147483648 for example
|
275 |
+
$this->memory_limit = $matches[1] * 1073741824;
|
276 |
+
}
|
277 |
+
if ($this->memory_limit <= 0) {
|
278 |
+
// memory limits probably disabled
|
279 |
+
} elseif ($this->memory_limit <= 4194304) {
|
280 |
+
$this->startup_error .= 'PHP has less than 4MB available memory and will very likely run out. Increase memory_limit in php.ini'."\n";
|
281 |
+
} elseif ($this->memory_limit <= 12582912) {
|
282 |
+
$this->startup_warning .= 'PHP has less than 12MB available memory and might run out if all modules are loaded. Increase memory_limit in php.ini'."\n";
|
283 |
+
}
|
284 |
|
285 |
+
// Check safe_mode off
|
286 |
+
if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) {
|
287 |
+
$this->warning('WARNING: Safe mode is on, shorten support disabled, md5data/sha1data for ogg vorbis disabled, ogg vorbos/flac tag writing disabled.');
|
288 |
+
}
|
289 |
|
290 |
+
if (($mbstring_func_overload = ini_get('mbstring.func_overload')) && ($mbstring_func_overload & 0x02)) {
|
291 |
+
// http://php.net/manual/en/mbstring.overload.php
|
292 |
+
// "mbstring.func_overload in php.ini is a positive value that represents a combination of bitmasks specifying the categories of functions to be overloaded. It should be set to 1 to overload the mail() function. 2 for string functions, 4 for regular expression functions"
|
293 |
+
// getID3 cannot run when string functions are overloaded. It doesn't matter if mail() or ereg* functions are overloaded since getID3 does not use those.
|
294 |
+
$this->startup_error .= 'WARNING: php.ini contains "mbstring.func_overload = '.ini_get('mbstring.func_overload').'", getID3 cannot run with this setting (bitmask 2 (string functions) cannot be set). Recommended to disable entirely.'."\n";
|
295 |
+
}
|
296 |
|
297 |
+
// Check for magic_quotes_runtime
|
298 |
+
if (function_exists('get_magic_quotes_runtime')) {
|
299 |
+
if (get_magic_quotes_runtime()) {
|
300 |
+
$this->startup_error .= 'magic_quotes_runtime must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_runtime(0) and set_magic_quotes_runtime(1).'."\n";
|
|
|
301 |
}
|
302 |
+
}
|
303 |
|
304 |
+
// Check for magic_quotes_gpc
|
305 |
+
if (function_exists('magic_quotes_gpc')) {
|
306 |
+
if (get_magic_quotes_gpc()) {
|
307 |
+
$this->startup_error .= 'magic_quotes_gpc must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_gpc(0) and set_magic_quotes_gpc(1).'."\n";
|
|
|
308 |
}
|
309 |
+
}
|
310 |
|
311 |
+
// Load support library
|
312 |
+
if (!include_once(GETID3_INCLUDEPATH.'getid3.lib.php')) {
|
313 |
+
$this->startup_error .= 'getid3.lib.php is missing or corrupt'."\n";
|
314 |
+
}
|
315 |
|
316 |
+
if ($this->option_max_2gb_check === null) {
|
317 |
+
$this->option_max_2gb_check = (PHP_INT_MAX <= 2147483647);
|
318 |
+
}
|
319 |
|
320 |
|
321 |
+
// Needed for Windows only:
|
322 |
+
// Define locations of helper applications for Shorten, VorbisComment, MetaFLAC
|
323 |
+
// as well as other helper functions such as head, tail, md5sum, etc
|
324 |
+
// This path cannot contain spaces, but the below code will attempt to get the
|
325 |
+
// 8.3-equivalent path automatically
|
326 |
+
// IMPORTANT: This path must include the trailing slash
|
327 |
+
if (GETID3_OS_ISWINDOWS && !defined('GETID3_HELPERAPPSDIR')) {
|
328 |
+
|
329 |
+
$helperappsdir = GETID3_INCLUDEPATH.'..'.DIRECTORY_SEPARATOR.'helperapps'; // must not have any space in this path
|
330 |
+
|
331 |
+
if (!is_dir($helperappsdir)) {
|
332 |
+
$this->startup_warning .= '"'.$helperappsdir.'" cannot be defined as GETID3_HELPERAPPSDIR because it does not exist'."\n";
|
333 |
+
} elseif (strpos(realpath($helperappsdir), ' ') !== false) {
|
334 |
+
$DirPieces = explode(DIRECTORY_SEPARATOR, realpath($helperappsdir));
|
335 |
+
$path_so_far = array();
|
336 |
+
foreach ($DirPieces as $key => $value) {
|
337 |
+
if (strpos($value, ' ') !== false) {
|
338 |
+
if (!empty($path_so_far)) {
|
339 |
+
$commandline = 'dir /x '.escapeshellarg(implode(DIRECTORY_SEPARATOR, $path_so_far));
|
340 |
+
$dir_listing = `$commandline`;
|
341 |
+
$lines = explode("\n", $dir_listing);
|
342 |
+
foreach ($lines as $line) {
|
343 |
+
$line = trim($line);
|
344 |
+
if (preg_match('#^([0-9/]{10}) +([0-9:]{4,5}( [AP]M)?) +(<DIR>|[0-9,]+) +([^ ]{0,11}) +(.+)$#', $line, $matches)) {
|
345 |
+
list($dummy, $date, $time, $ampm, $filesize, $shortname, $filename) = $matches;
|
346 |
+
if ((strtoupper($filesize) == '<DIR>') && (strtolower($filename) == strtolower($value))) {
|
347 |
+
$value = $shortname;
|
|
|
348 |
}
|
349 |
}
|
|
|
|
|
350 |
}
|
351 |
+
} else {
|
352 |
+
$this->startup_warning .= 'GETID3_HELPERAPPSDIR must not have any spaces in it - use 8dot3 naming convention if neccesary. You can run "dir /x" from the commandline to see the correct 8.3-style names.'."\n";
|
353 |
}
|
|
|
354 |
}
|
355 |
+
$path_so_far[] = $value;
|
356 |
}
|
357 |
+
$helperappsdir = implode(DIRECTORY_SEPARATOR, $path_so_far);
|
358 |
}
|
359 |
+
define('GETID3_HELPERAPPSDIR', $helperappsdir.DIRECTORY_SEPARATOR);
|
|
|
360 |
}
|
361 |
|
362 |
+
if (!empty($this->startup_error)) {
|
363 |
+
echo $this->startup_error;
|
364 |
+
throw new getid3_exception($this->startup_error);
|
365 |
}
|
366 |
+
}
|
367 |
|
368 |
+
/**
|
369 |
+
* @return string
|
370 |
+
*/
|
371 |
+
public function version() {
|
372 |
+
return self::VERSION;
|
373 |
+
}
|
374 |
|
375 |
+
/**
|
376 |
+
* @return int
|
377 |
+
*/
|
378 |
+
public function fread_buffer_size() {
|
379 |
+
return $this->option_fread_buffer_size;
|
380 |
+
}
|
381 |
|
382 |
+
/**
|
383 |
+
* @param array $optArray
|
384 |
+
*
|
385 |
+
* @return bool
|
386 |
+
*/
|
387 |
+
public function setOption($optArray) {
|
388 |
+
if (!is_array($optArray) || empty($optArray)) {
|
389 |
+
return false;
|
390 |
+
}
|
391 |
+
foreach ($optArray as $opt => $val) {
|
392 |
+
if (isset($this->$opt) === false) {
|
393 |
+
continue;
|
394 |
}
|
395 |
+
$this->$opt = $val;
|
396 |
}
|
397 |
+
return true;
|
398 |
+
}
|
399 |
|
400 |
+
/**
|
401 |
+
* @param string $filename
|
402 |
+
* @param int $filesize
|
403 |
+
*
|
404 |
+
* @return bool
|
405 |
+
*
|
406 |
+
* @throws getid3_exception
|
407 |
+
*/
|
408 |
+
public function openfile($filename, $filesize=null, $fp=null) {
|
409 |
+
try {
|
410 |
+
if (!empty($this->startup_error)) {
|
411 |
+
throw new getid3_exception($this->startup_error);
|
412 |
+
}
|
413 |
+
if (!empty($this->startup_warning)) {
|
414 |
+
foreach (explode("\n", $this->startup_warning) as $startup_warning) {
|
415 |
+
$this->warning($startup_warning);
|
416 |
}
|
417 |
+
}
|
418 |
|
419 |
+
// init result array and set parameters
|
420 |
+
$this->filename = $filename;
|
421 |
+
$this->info = array();
|
422 |
+
$this->info['GETID3_VERSION'] = $this->version();
|
423 |
+
$this->info['php_memory_limit'] = (($this->memory_limit > 0) ? $this->memory_limit : false);
|
424 |
|
425 |
+
// remote files not supported
|
426 |
+
if (preg_match('#^(ht|f)tp://#', $filename)) {
|
427 |
+
throw new getid3_exception('Remote files are not supported - please copy the file locally first');
|
428 |
+
}
|
429 |
|
430 |
+
$filename = str_replace('/', DIRECTORY_SEPARATOR, $filename);
|
431 |
+
//$filename = preg_replace('#(?<!gs:)('.preg_quote(DIRECTORY_SEPARATOR).'{2,})#', DIRECTORY_SEPARATOR, $filename);
|
432 |
|
433 |
+
// open local file
|
434 |
+
//if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see https://www.getid3.org/phpBB3/viewtopic.php?t=1720
|
435 |
+
if (($fp != null) && ((get_resource_type($fp) == 'file') || (get_resource_type($fp) == 'stream'))) {
|
436 |
+
$this->fp = $fp;
|
437 |
+
} elseif ((is_readable($filename) || file_exists($filename)) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) {
|
438 |
+
// great
|
439 |
+
} else {
|
440 |
+
$errormessagelist = array();
|
441 |
+
if (!is_readable($filename)) {
|
442 |
+
$errormessagelist[] = '!is_readable';
|
443 |
+
}
|
444 |
+
if (!is_file($filename)) {
|
445 |
+
$errormessagelist[] = '!is_file';
|
446 |
+
}
|
447 |
+
if (!file_exists($filename)) {
|
448 |
+
$errormessagelist[] = '!file_exists';
|
449 |
+
}
|
450 |
+
if (empty($errormessagelist)) {
|
451 |
+
$errormessagelist[] = 'fopen failed';
|
452 |
}
|
453 |
+
throw new getid3_exception('Could not open "'.$filename.'" ('.implode('; ', $errormessagelist).')');
|
454 |
+
}
|
455 |
|
456 |
+
$this->info['filesize'] = (!is_null($filesize) ? $filesize : filesize($filename));
|
457 |
+
// set redundant parameters - might be needed in some include file
|
458 |
+
// filenames / filepaths in getID3 are always expressed with forward slashes (unix-style) for both Windows and other to try and minimize confusion
|
459 |
+
$filename = str_replace('\\', '/', $filename);
|
460 |
+
$this->info['filepath'] = str_replace('\\', '/', realpath(dirname($filename)));
|
461 |
+
$this->info['filename'] = getid3_lib::mb_basename($filename);
|
462 |
+
$this->info['filenamepath'] = $this->info['filepath'].'/'.$this->info['filename'];
|
463 |
+
|
464 |
+
// set more parameters
|
465 |
+
$this->info['avdataoffset'] = 0;
|
466 |
+
$this->info['avdataend'] = $this->info['filesize'];
|
467 |
+
$this->info['fileformat'] = ''; // filled in later
|
468 |
+
$this->info['audio']['dataformat'] = ''; // filled in later, unset if not used
|
469 |
+
$this->info['video']['dataformat'] = ''; // filled in later, unset if not used
|
470 |
+
$this->info['tags'] = array(); // filled in later, unset if not used
|
471 |
+
$this->info['error'] = array(); // filled in later, unset if not used
|
472 |
+
$this->info['warning'] = array(); // filled in later, unset if not used
|
473 |
+
$this->info['comments'] = array(); // filled in later, unset if not used
|
474 |
+
$this->info['encoding'] = $this->encoding; // required by id3v2 and iso modules - can be unset at the end if desired
|
475 |
+
|
476 |
+
// option_max_2gb_check
|
477 |
+
if ($this->option_max_2gb_check) {
|
478 |
+
// PHP (32-bit all, and 64-bit Windows) doesn't support integers larger than 2^31 (~2GB)
|
479 |
+
// filesize() simply returns (filesize % (pow(2, 32)), no matter the actual filesize
|
480 |
+
// ftell() returns 0 if seeking to the end is beyond the range of unsigned integer
|
481 |
+
$fseek = fseek($this->fp, 0, SEEK_END);
|
482 |
+
if (($fseek < 0) || (($this->info['filesize'] != 0) && (ftell($this->fp) == 0)) ||
|
483 |
+
($this->info['filesize'] < 0) ||
|
484 |
+
(ftell($this->fp) < 0)) {
|
485 |
$real_filesize = getid3_lib::getFileSizeSyscall($this->info['filenamepath']);
|
486 |
|
487 |
if ($real_filesize === false) {
|
491 |
} elseif (getid3_lib::intValueSupported($real_filesize)) {
|
492 |
unset($this->info['filesize']);
|
493 |
fclose($this->fp);
|
494 |
+
throw new getid3_exception('PHP seems to think the file is larger than '.round(PHP_INT_MAX / 1073741824).'GB, but filesystem reports it as '.number_format($real_filesize / 1073741824, 3).'GB, please report to info@getid3.org');
|
495 |
}
|
496 |
$this->info['filesize'] = $real_filesize;
|
497 |
+
$this->warning('File is larger than '.round(PHP_INT_MAX / 1073741824).'GB (filesystem reports it as '.number_format($real_filesize / 1073741824, 3).'GB) and is not properly supported by PHP.');
|
|
|
498 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
499 |
}
|
500 |
+
|
501 |
+
return true;
|
502 |
+
|
503 |
+
} catch (Exception $e) {
|
504 |
+
$this->error($e->getMessage());
|
505 |
}
|
506 |
+
return false;
|
507 |
+
}
|
508 |
|
509 |
+
/**
|
510 |
+
* analyze file
|
511 |
+
*
|
512 |
+
* @param string $filename
|
513 |
+
* @param int $filesize
|
514 |
+
* @param string $original_filename
|
515 |
+
*
|
516 |
+
* @return array
|
517 |
+
*/
|
518 |
+
public function analyze($filename, $filesize=null, $original_filename='', $fp=null) {
|
519 |
+
try {
|
520 |
+
if (!$this->openfile($filename, $filesize, $fp)) {
|
521 |
+
return $this->info;
|
522 |
+
}
|
523 |
|
524 |
+
// Handle tags
|
525 |
+
foreach (array('id3v2'=>'id3v2', 'id3v1'=>'id3v1', 'apetag'=>'ape', 'lyrics3'=>'lyrics3') as $tag_name => $tag_key) {
|
526 |
+
$option_tag = 'option_tag_'.$tag_name;
|
527 |
+
if ($this->$option_tag) {
|
528 |
+
$this->include_module('tag.'.$tag_name);
|
529 |
+
try {
|
530 |
+
$tag_class = 'getid3_'.$tag_name;
|
531 |
+
$tag = new $tag_class($this);
|
532 |
+
$tag->Analyze();
|
|
|
|
|
|
|
|
|
533 |
}
|
534 |
+
catch (getid3_exception $e) {
|
535 |
+
throw $e;
|
|
|
|
|
|
|
|
|
|
|
536 |
}
|
537 |
}
|
538 |
+
}
|
539 |
+
if (isset($this->info['id3v2']['tag_offset_start'])) {
|
540 |
+
$this->info['avdataoffset'] = max($this->info['avdataoffset'], $this->info['id3v2']['tag_offset_end']);
|
541 |
+
}
|
542 |
+
foreach (array('id3v1'=>'id3v1', 'apetag'=>'ape', 'lyrics3'=>'lyrics3') as $tag_name => $tag_key) {
|
543 |
+
if (isset($this->info[$tag_key]['tag_offset_start'])) {
|
544 |
+
$this->info['avdataend'] = min($this->info['avdataend'], $this->info[$tag_key]['tag_offset_start']);
|
|
|
|
|
|
|
|
|
545 |
}
|
546 |
+
}
|
547 |
|
548 |
+
// ID3v2 detection (NOT parsing), even if ($this->option_tag_id3v2 == false) done to make fileformat easier
|
549 |
+
if (!$this->option_tag_id3v2) {
|
550 |
+
fseek($this->fp, 0);
|
551 |
+
$header = fread($this->fp, 10);
|
552 |
+
if ((substr($header, 0, 3) == 'ID3') && (strlen($header) == 10)) {
|
553 |
+
$this->info['id3v2']['header'] = true;
|
554 |
+
$this->info['id3v2']['majorversion'] = ord($header{3});
|
555 |
+
$this->info['id3v2']['minorversion'] = ord($header{4});
|
556 |
+
$this->info['avdataoffset'] += getid3_lib::BigEndian2Int(substr($header, 6, 4), 1) + 10; // length of ID3v2 tag in 10-byte header doesn't include 10-byte header length
|
|
|
|
|
557 |
}
|
558 |
+
}
|
559 |
|
560 |
+
// read 32 kb file data
|
561 |
+
fseek($this->fp, $this->info['avdataoffset']);
|
562 |
+
$formattest = fread($this->fp, 32774);
|
|
|
|
|
|
|
|
|
|
|
|
|
563 |
|
564 |
+
// determine format
|
565 |
+
$determined_format = $this->GetFileFormat($formattest, ($original_filename ? $original_filename : $filename));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
566 |
|
567 |
+
// unable to determine file format
|
568 |
+
if (!$determined_format) {
|
569 |
+
fclose($this->fp);
|
570 |
+
return $this->error('unable to determine file format');
|
571 |
+
}
|
572 |
|
573 |
+
// check for illegal ID3 tags
|
574 |
+
if (isset($determined_format['fail_id3']) && (in_array('id3v1', $this->info['tags']) || in_array('id3v2', $this->info['tags']))) {
|
575 |
+
if ($determined_format['fail_id3'] === 'ERROR') {
|
576 |
fclose($this->fp);
|
577 |
+
return $this->error('ID3 tags not allowed on this file type.');
|
578 |
+
} elseif ($determined_format['fail_id3'] === 'WARNING') {
|
579 |
+
$this->warning('ID3 tags not allowed on this file type.');
|
580 |
}
|
581 |
+
}
|
582 |
|
583 |
+
// check for illegal APE tags
|
584 |
+
if (isset($determined_format['fail_ape']) && in_array('ape', $this->info['tags'])) {
|
585 |
+
if ($determined_format['fail_ape'] === 'ERROR') {
|
586 |
+
fclose($this->fp);
|
587 |
+
return $this->error('APE tags not allowed on this file type.');
|
588 |
+
} elseif ($determined_format['fail_ape'] === 'WARNING') {
|
589 |
+
$this->warning('APE tags not allowed on this file type.');
|
|
|
|
|
|
|
590 |
}
|
591 |
+
}
|
592 |
|
593 |
+
// set mime type
|
594 |
+
$this->info['mime_type'] = $determined_format['mime_type'];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
595 |
|
596 |
+
// supported format signature pattern detected, but module deleted
|
597 |
+
if (!file_exists(GETID3_INCLUDEPATH.$determined_format['include'])) {
|
598 |
fclose($this->fp);
|
599 |
+
return $this->error('Format not supported, module "'.$determined_format['include'].'" was removed.');
|
600 |
+
}
|
601 |
|
602 |
+
// module requires mb_convert_encoding/iconv support
|
603 |
+
// Check encoding/iconv support
|
604 |
+
if (!empty($determined_format['iconv_req']) && !function_exists('mb_convert_encoding') && !function_exists('iconv') && !in_array($this->encoding, array('ISO-8859-1', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'UTF-16'))) {
|
605 |
+
$errormessage = 'mb_convert_encoding() or iconv() support is required for this module ('.$determined_format['include'].') for encodings other than ISO-8859-1, UTF-8, UTF-16LE, UTF16-BE, UTF-16. ';
|
606 |
+
if (GETID3_OS_ISWINDOWS) {
|
607 |
+
$errormessage .= 'PHP does not have mb_convert_encoding() or iconv() support. Please enable php_mbstring.dll / php_iconv.dll in php.ini, and copy php_mbstring.dll / iconv.dll from c:/php/dlls to c:/windows/system32';
|
608 |
+
} else {
|
609 |
+
$errormessage .= 'PHP is not compiled with mb_convert_encoding() or iconv() support. Please recompile with the --enable-mbstring / --with-iconv switch';
|
610 |
}
|
611 |
+
return $this->error($errormessage);
|
612 |
+
}
|
613 |
|
614 |
+
// include module
|
615 |
+
include_once(GETID3_INCLUDEPATH.$determined_format['include']);
|
|
|
|
|
|
|
|
|
|
|
|
|
616 |
|
617 |
+
// instantiate module class
|
618 |
+
$class_name = 'getid3_'.$determined_format['module'];
|
619 |
+
if (!class_exists($class_name)) {
|
620 |
+
return $this->error('Format not supported, module "'.$determined_format['include'].'" is corrupt.');
|
621 |
+
}
|
622 |
+
$class = new $class_name($this);
|
623 |
+
$class->Analyze();
|
624 |
+
unset($class);
|
625 |
|
626 |
+
// close file
|
627 |
+
fclose($this->fp);
|
|
|
|
|
628 |
|
629 |
+
// process all tags - copy to 'tags' and convert charsets
|
630 |
+
if ($this->option_tags_process) {
|
631 |
+
$this->HandleAllTags();
|
632 |
+
}
|
633 |
|
634 |
+
// perform more calculations
|
635 |
+
if ($this->option_extra_info) {
|
636 |
+
$this->ChannelsBitratePlaytimeCalculations();
|
637 |
+
$this->CalculateCompressionRatioVideo();
|
638 |
+
$this->CalculateCompressionRatioAudio();
|
639 |
+
$this->CalculateReplayGain();
|
640 |
+
$this->ProcessAudioStreams();
|
641 |
}
|
642 |
|
643 |
+
// get the MD5 sum of the audio/video portion of the file - without ID3/APE/Lyrics3/etc header/footer tags
|
644 |
+
if ($this->option_md5_data) {
|
645 |
+
// do not calc md5_data if md5_data_source is present - set by flac only - future MPC/SV8 too
|
646 |
+
if (!$this->option_md5_data_source || empty($this->info['md5_data_source'])) {
|
647 |
+
$this->getHashdata('md5');
|
648 |
+
}
|
649 |
+
}
|
650 |
|
651 |
+
// get the SHA1 sum of the audio/video portion of the file - without ID3/APE/Lyrics3/etc header/footer tags
|
652 |
+
if ($this->option_sha1_data) {
|
653 |
+
$this->getHashdata('sha1');
|
654 |
+
}
|
655 |
|
656 |
+
// remove undesired keys
|
|
|
657 |
$this->CleanUp();
|
658 |
+
|
659 |
+
} catch (Exception $e) {
|
660 |
+
$this->error('Caught exception: '.$e->getMessage());
|
|
|
|
|
661 |
}
|
662 |
|
663 |
+
// return info array
|
664 |
+
return $this->info;
|
665 |
+
}
|
666 |
|
667 |
+
|
668 |
+
/**
|
669 |
+
* Error handling.
|
670 |
+
*
|
671 |
+
* @param string $message
|
672 |
+
*
|
673 |
+
* @return array
|
674 |
+
*/
|
675 |
+
public function error($message) {
|
676 |
+
$this->CleanUp();
|
677 |
+
if (!isset($this->info['error'])) {
|
678 |
+
$this->info['error'] = array();
|
679 |
}
|
680 |
+
$this->info['error'][] = $message;
|
681 |
+
return $this->info;
|
682 |
+
}
|
683 |
|
684 |
|
685 |
+
/**
|
686 |
+
* Warning handling.
|
687 |
+
*
|
688 |
+
* @param string $message
|
689 |
+
*
|
690 |
+
* @return bool
|
691 |
+
*/
|
692 |
+
public function warning($message) {
|
693 |
+
$this->info['warning'][] = $message;
|
694 |
+
return true;
|
695 |
+
}
|
696 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
697 |
|
698 |
+
/**
|
699 |
+
* @return bool
|
700 |
+
*/
|
701 |
+
private function CleanUp() {
|
702 |
+
|
703 |
+
// remove possible empty keys
|
704 |
+
$AVpossibleEmptyKeys = array('dataformat', 'bits_per_sample', 'encoder_options', 'streams', 'bitrate');
|
705 |
+
foreach ($AVpossibleEmptyKeys as $dummy => $key) {
|
706 |
+
if (empty($this->info['audio'][$key]) && isset($this->info['audio'][$key])) {
|
707 |
+
unset($this->info['audio'][$key]);
|
708 |
+
}
|
709 |
+
if (empty($this->info['video'][$key]) && isset($this->info['video'][$key])) {
|
710 |
+
unset($this->info['video'][$key]);
|
711 |
}
|
712 |
+
}
|
713 |
|
714 |
+
// remove empty root keys
|
715 |
+
if (!empty($this->info)) {
|
716 |
+
foreach ($this->info as $key => $value) {
|
717 |
+
if (empty($this->info[$key]) && ($this->info[$key] !== 0) && ($this->info[$key] !== '0')) {
|
718 |
+
unset($this->info[$key]);
|
|
|
|
|
719 |
}
|
720 |
}
|
721 |
+
}
|
722 |
|
723 |
+
// remove meaningless entries from unknown-format files
|
724 |
+
if (empty($this->info['fileformat'])) {
|
725 |
+
if (isset($this->info['avdataoffset'])) {
|
726 |
+
unset($this->info['avdataoffset']);
|
727 |
}
|
728 |
+
if (isset($this->info['avdataend'])) {
|
729 |
+
unset($this->info['avdataend']);
|
730 |
}
|
731 |
+
}
|
732 |
|
733 |
+
// remove possible duplicated identical entries
|
734 |
+
if (!empty($this->info['error'])) {
|
735 |
+
$this->info['error'] = array_values(array_unique($this->info['error']));
|
|
|
736 |
}
|
737 |
+
if (!empty($this->info['warning'])) {
|
738 |
+
$this->info['warning'] = array_values(array_unique($this->info['warning']));
|
739 |
+
}
|
740 |
+
|
741 |
+
// remove "global variable" type keys
|
742 |
+
unset($this->info['php_memory_limit']);
|
743 |
|
744 |
+
return true;
|
745 |
+
}
|
746 |
|
747 |
+
/**
|
748 |
+
* Return array containing information about all supported formats.
|
749 |
+
*
|
750 |
+
* @return array
|
751 |
+
*/
|
752 |
+
public function GetFileFormatArray() {
|
753 |
+
static $format_info = array();
|
754 |
+
if (empty($format_info)) {
|
755 |
+
$format_info = array(
|
756 |
+
|
757 |
+
// Audio formats
|
758 |
+
|
759 |
+
// AC-3 - audio - Dolby AC-3 / Dolby Digital
|
760 |
+
'ac3' => array(
|
761 |
+
'pattern' => '^\\x0B\\x77',
|
762 |
+
'group' => 'audio',
|
763 |
+
'module' => 'ac3',
|
764 |
+
'mime_type' => 'audio/ac3',
|
765 |
+
),
|
766 |
+
|
767 |
+
// AAC - audio - Advanced Audio Coding (AAC) - ADIF format
|
768 |
+
'adif' => array(
|
769 |
+
'pattern' => '^ADIF',
|
770 |
+
'group' => 'audio',
|
771 |
+
'module' => 'aac',
|
772 |
+
'mime_type' => 'audio/aac',
|
773 |
+
'fail_ape' => 'WARNING',
|
774 |
+
),
|
775 |
+
|
776 |
+
/*
|
777 |
+
// AA - audio - Audible Audiobook
|
778 |
+
'aa' => array(
|
779 |
+
'pattern' => '^.{4}\\x57\\x90\\x75\\x36',
|
780 |
+
'group' => 'audio',
|
781 |
+
'module' => 'aa',
|
782 |
+
'mime_type' => 'audio/audible',
|
783 |
+
),
|
784 |
+
*/
|
785 |
+
// AAC - audio - Advanced Audio Coding (AAC) - ADTS format (very similar to MP3)
|
786 |
+
'adts' => array(
|
787 |
+
'pattern' => '^\\xFF[\\xF0-\\xF1\\xF8-\\xF9]',
|
788 |
+
'group' => 'audio',
|
789 |
+
'module' => 'aac',
|
790 |
+
'mime_type' => 'audio/aac',
|
791 |
+
'fail_ape' => 'WARNING',
|
792 |
+
),
|
793 |
+
|
794 |
+
|
795 |
+
// AU - audio - NeXT/Sun AUdio (AU)
|
796 |
+
'au' => array(
|
797 |
+
'pattern' => '^\\.snd',
|
798 |
+
'group' => 'audio',
|
799 |
+
'module' => 'au',
|
800 |
+
'mime_type' => 'audio/basic',
|
801 |
+
),
|
802 |
+
|
803 |
+
// AMR - audio - Adaptive Multi Rate
|
804 |
+
'amr' => array(
|
805 |
+
'pattern' => '^\\x23\\x21AMR\\x0A', // #!AMR[0A]
|
806 |
+
'group' => 'audio',
|
807 |
+
'module' => 'amr',
|
808 |
+
'mime_type' => 'audio/amr',
|
809 |
+
),
|
810 |
+
|
811 |
+
// AVR - audio - Audio Visual Research
|
812 |
+
'avr' => array(
|
813 |
+
'pattern' => '^2BIT',
|
814 |
+
'group' => 'audio',
|
815 |
+
'module' => 'avr',
|
816 |
+
'mime_type' => 'application/octet-stream',
|
817 |
+
),
|
818 |
+
|
819 |
+
// BONK - audio - Bonk v0.9+
|
820 |
+
'bonk' => array(
|
821 |
+
'pattern' => '^\\x00(BONK|INFO|META| ID3)',
|
822 |
+
'group' => 'audio',
|
823 |
+
'module' => 'bonk',
|
824 |
+
'mime_type' => 'audio/xmms-bonk',
|
825 |
+
),
|
826 |
+
|
827 |
+
// DSF - audio - Direct Stream Digital (DSD) Storage Facility files (DSF) - https://en.wikipedia.org/wiki/Direct_Stream_Digital
|
828 |
+
'dsf' => array(
|
829 |
+
'pattern' => '^DSD ', // including trailing space: 44 53 44 20
|
830 |
+
'group' => 'audio',
|
831 |
+
'module' => 'dsf',
|
832 |
+
'mime_type' => 'audio/dsd',
|
833 |
+
),
|
834 |
+
|
835 |
+
// DSS - audio - Digital Speech Standard
|
836 |
+
'dss' => array(
|
837 |
+
'pattern' => '^[\\x02-\\x06]ds[s2]',
|
838 |
+
'group' => 'audio',
|
839 |
+
'module' => 'dss',
|
840 |
+
'mime_type' => 'application/octet-stream',
|
841 |
+
),
|
842 |
+
|
843 |
+
// DTS - audio - Dolby Theatre System
|
844 |
+
'dts' => array(
|
845 |
+
'pattern' => '^\\x7F\\xFE\\x80\\x01',
|
846 |
+
'group' => 'audio',
|
847 |
+
'module' => 'dts',
|
848 |
+
'mime_type' => 'audio/dts',
|
849 |
+
),
|
850 |
+
|
851 |
+
// FLAC - audio - Free Lossless Audio Codec
|
852 |
+
'flac' => array(
|
853 |
+
'pattern' => '^fLaC',
|
854 |
+
'group' => 'audio',
|
855 |
+
'module' => 'flac',
|
856 |
+
'mime_type' => 'audio/flac',
|
857 |
+
),
|
858 |
+
|
859 |
+
// LA - audio - Lossless Audio (LA)
|
860 |
+
'la' => array(
|
861 |
+
'pattern' => '^LA0[2-4]',
|
862 |
+
'group' => 'audio',
|
863 |
+
'module' => 'la',
|
864 |
+
'mime_type' => 'application/octet-stream',
|
865 |
+
),
|
866 |
+
|
867 |
+
// LPAC - audio - Lossless Predictive Audio Compression (LPAC)
|
868 |
+
'lpac' => array(
|
869 |
+
'pattern' => '^LPAC',
|
870 |
+
'group' => 'audio',
|
871 |
+
'module' => 'lpac',
|
872 |
+
'mime_type' => 'application/octet-stream',
|
873 |
+
),
|
874 |
+
|
875 |
+
// MIDI - audio - MIDI (Musical Instrument Digital Interface)
|
876 |
+
'midi' => array(
|
877 |
+
'pattern' => '^MThd',
|
878 |
+
'group' => 'audio',
|
879 |
+
'module' => 'midi',
|
880 |
+
'mime_type' => 'audio/midi',
|
881 |
+
),
|
882 |
+
|
883 |
+
// MAC - audio - Monkey's Audio Compressor
|
884 |
+
'mac' => array(
|
885 |
+
'pattern' => '^MAC ',
|
886 |
+
'group' => 'audio',
|
887 |
+
'module' => 'monkey',
|
888 |
+
'mime_type' => 'audio/x-monkeys-audio',
|
889 |
+
),
|
890 |
|
891 |
// has been known to produce false matches in random files (e.g. JPEGs), leave out until more precise matching available
|
892 |
// // MOD - audio - MODule (assorted sub-formats)
|
898 |
// 'mime_type' => 'audio/mod',
|
899 |
// ),
|
900 |
|
901 |
+
// MOD - audio - MODule (Impulse Tracker)
|
902 |
+
'it' => array(
|
903 |
+
'pattern' => '^IMPM',
|
904 |
+
'group' => 'audio',
|
905 |
+
'module' => 'mod',
|
906 |
+
//'option' => 'it',
|
907 |
+
'mime_type' => 'audio/it',
|
908 |
+
),
|
909 |
+
|
910 |
+
// MOD - audio - MODule (eXtended Module, various sub-formats)
|
911 |
+
'xm' => array(
|
912 |
+
'pattern' => '^Extended Module',
|
913 |
+
'group' => 'audio',
|
914 |
+
'module' => 'mod',
|
915 |
+
//'option' => 'xm',
|
916 |
+
'mime_type' => 'audio/xm',
|
917 |
+
),
|
918 |
+
|
919 |
+
// MOD - audio - MODule (ScreamTracker)
|
920 |
+
's3m' => array(
|
921 |
+
'pattern' => '^.{44}SCRM',
|
922 |
+
'group' => 'audio',
|
923 |
+
'module' => 'mod',
|
924 |
+
//'option' => 's3m',
|
925 |
+
'mime_type' => 'audio/s3m',
|
926 |
+
),
|
927 |
+
|
928 |
+
// MPC - audio - Musepack / MPEGplus
|
929 |
+
'mpc' => array(
|
930 |
+
'pattern' => '^(MPCK|MP\\+|[\\x00\\x01\\x10\\x11\\x40\\x41\\x50\\x51\\x80\\x81\\x90\\x91\\xC0\\xC1\\xD0\\xD1][\\x20-\\x37][\\x00\\x20\\x40\\x60\\x80\\xA0\\xC0\\xE0])',
|
931 |
+
'group' => 'audio',
|
932 |
+
'module' => 'mpc',
|
933 |
+
'mime_type' => 'audio/x-musepack',
|
934 |
+
),
|
935 |
+
|
936 |
+
// MP3 - audio - MPEG-audio Layer 3 (very similar to AAC-ADTS)
|
937 |
+
'mp3' => array(
|
938 |
+
'pattern' => '^\\xFF[\\xE2-\\xE7\\xF2-\\xF7\\xFA-\\xFF][\\x00-\\x0B\\x10-\\x1B\\x20-\\x2B\\x30-\\x3B\\x40-\\x4B\\x50-\\x5B\\x60-\\x6B\\x70-\\x7B\\x80-\\x8B\\x90-\\x9B\\xA0-\\xAB\\xB0-\\xBB\\xC0-\\xCB\\xD0-\\xDB\\xE0-\\xEB\\xF0-\\xFB]',
|
939 |
+
'group' => 'audio',
|
940 |
+
'module' => 'mp3',
|
941 |
+
'mime_type' => 'audio/mpeg',
|
942 |
+
),
|
943 |
+
|
944 |
+
// OFR - audio - OptimFROG
|
945 |
+
'ofr' => array(
|
946 |
+
'pattern' => '^(\\*RIFF|OFR)',
|
947 |
+
'group' => 'audio',
|
948 |
+
'module' => 'optimfrog',
|
949 |
+
'mime_type' => 'application/octet-stream',
|
950 |
+
),
|
951 |
+
|
952 |
+
// RKAU - audio - RKive AUdio compressor
|
953 |
+
'rkau' => array(
|
954 |
+
'pattern' => '^RKA',
|
955 |
+
'group' => 'audio',
|
956 |
+
'module' => 'rkau',
|
957 |
+
'mime_type' => 'application/octet-stream',
|
958 |
+
),
|
959 |
+
|
960 |
+
// SHN - audio - Shorten
|
961 |
+
'shn' => array(
|
962 |
+
'pattern' => '^ajkg',
|
963 |
+
'group' => 'audio',
|
964 |
+
'module' => 'shorten',
|
965 |
+
'mime_type' => 'audio/xmms-shn',
|
966 |
+
'fail_id3' => 'ERROR',
|
967 |
+
'fail_ape' => 'ERROR',
|
968 |
+
),
|
969 |
+
|
970 |
+
// TTA - audio - TTA Lossless Audio Compressor (http://tta.corecodec.org)
|
971 |
+
'tta' => array(
|
972 |
+
'pattern' => '^TTA', // could also be '^TTA(\\x01|\\x02|\\x03|2|1)'
|
973 |
+
'group' => 'audio',
|
974 |
+
'module' => 'tta',
|
975 |
+
'mime_type' => 'application/octet-stream',
|
976 |
+
),
|
977 |
+
|
978 |
+
// VOC - audio - Creative Voice (VOC)
|
979 |
+
'voc' => array(
|
980 |
+
'pattern' => '^Creative Voice File',
|
981 |
+
'group' => 'audio',
|
982 |
+
'module' => 'voc',
|
983 |
+
'mime_type' => 'audio/voc',
|
984 |
+
),
|
985 |
+
|
986 |
+
// VQF - audio - transform-domain weighted interleave Vector Quantization Format (VQF)
|
987 |
+
'vqf' => array(
|
988 |
+
'pattern' => '^TWIN',
|
989 |
+
'group' => 'audio',
|
990 |
+
'module' => 'vqf',
|
991 |
+
'mime_type' => 'application/octet-stream',
|
992 |
+
),
|
993 |
+
|
994 |
+
// WV - audio - WavPack (v4.0+)
|
995 |
+
'wv' => array(
|
996 |
+
'pattern' => '^wvpk',
|
997 |
+
'group' => 'audio',
|
998 |
+
'module' => 'wavpack',
|
999 |
+
'mime_type' => 'application/octet-stream',
|
1000 |
+
),
|
1001 |
+
|
1002 |
+
|
1003 |
+
// Audio-Video formats
|
1004 |
+
|
1005 |
+
// ASF - audio/video - Advanced Streaming Format, Windows Media Video, Windows Media Audio
|
1006 |
+
'asf' => array(
|
1007 |
+
'pattern' => '^\\x30\\x26\\xB2\\x75\\x8E\\x66\\xCF\\x11\\xA6\\xD9\\x00\\xAA\\x00\\x62\\xCE\\x6C',
|
1008 |
+
'group' => 'audio-video',
|
1009 |
+
'module' => 'asf',
|
1010 |
+
'mime_type' => 'video/x-ms-asf',
|
1011 |
+
'iconv_req' => false,
|
1012 |
+
),
|
1013 |
+
|
1014 |
+
// BINK - audio/video - Bink / Smacker
|
1015 |
+
'bink' => array(
|
1016 |
+
'pattern' => '^(BIK|SMK)',
|
1017 |
+
'group' => 'audio-video',
|
1018 |
+
'module' => 'bink',
|
1019 |
+
'mime_type' => 'application/octet-stream',
|
1020 |
+
),
|
1021 |
+
|
1022 |
+
// FLV - audio/video - FLash Video
|
1023 |
+
'flv' => array(
|
1024 |
+
'pattern' => '^FLV[\\x01]',
|
1025 |
+
'group' => 'audio-video',
|
1026 |
+
'module' => 'flv',
|
1027 |
+
'mime_type' => 'video/x-flv',
|
1028 |
+
),
|
1029 |
+
|
1030 |
+
// MKAV - audio/video - Mastroka
|
1031 |
+
'matroska' => array(
|
1032 |
+
'pattern' => '^\\x1A\\x45\\xDF\\xA3',
|
1033 |
+
'group' => 'audio-video',
|
1034 |
+
'module' => 'matroska',
|
1035 |
+
'mime_type' => 'video/x-matroska', // may also be audio/x-matroska
|
1036 |
+
),
|
1037 |
+
|
1038 |
+
// MPEG - audio/video - MPEG (Moving Pictures Experts Group)
|
1039 |
+
'mpeg' => array(
|
1040 |
+
'pattern' => '^\\x00\\x00\\x01[\\xB3\\xBA]',
|
1041 |
+
'group' => 'audio-video',
|
1042 |
+
'module' => 'mpeg',
|
1043 |
+
'mime_type' => 'video/mpeg',
|
1044 |
+
),
|
1045 |
+
|
1046 |
+
// NSV - audio/video - Nullsoft Streaming Video (NSV)
|
1047 |
+
'nsv' => array(
|
1048 |
+
'pattern' => '^NSV[sf]',
|
1049 |
+
'group' => 'audio-video',
|
1050 |
+
'module' => 'nsv',
|
1051 |
+
'mime_type' => 'application/octet-stream',
|
1052 |
+
),
|
1053 |
+
|
1054 |
+
// Ogg - audio/video - Ogg (Ogg-Vorbis, Ogg-FLAC, Speex, Ogg-Theora(*), Ogg-Tarkin(*))
|
1055 |
+
'ogg' => array(
|
1056 |
+
'pattern' => '^OggS',
|
1057 |
+
'group' => 'audio',
|
1058 |
+
'module' => 'ogg',
|
1059 |
+
'mime_type' => 'application/ogg',
|
1060 |
+
'fail_id3' => 'WARNING',
|
1061 |
+
'fail_ape' => 'WARNING',
|
1062 |
+
),
|
1063 |
+
|
1064 |
+
// QT - audio/video - Quicktime
|
1065 |
+
'quicktime' => array(
|
1066 |
+
'pattern' => '^.{4}(cmov|free|ftyp|mdat|moov|pnot|skip|wide)',
|
1067 |
+
'group' => 'audio-video',
|
1068 |
+
'module' => 'quicktime',
|
1069 |
+
'mime_type' => 'video/quicktime',
|
1070 |
+
),
|
1071 |
+
|
1072 |
+
// RIFF - audio/video - Resource Interchange File Format (RIFF) / WAV / AVI / CD-audio / SDSS = renamed variant used by SmartSound QuickTracks (www.smartsound.com) / FORM = Audio Interchange File Format (AIFF)
|
1073 |
+
'riff' => array(
|
1074 |
+
'pattern' => '^(RIFF|SDSS|FORM)',
|
1075 |
+
'group' => 'audio-video',
|
1076 |
+
'module' => 'riff',
|
1077 |
+
'mime_type' => 'audio/wav',
|
1078 |
+
'fail_ape' => 'WARNING',
|
1079 |
+
),
|
1080 |
+
|
1081 |
+
// Real - audio/video - RealAudio, RealVideo
|
1082 |
+
'real' => array(
|
1083 |
+
'pattern' => '^\\.(RMF|ra)',
|
1084 |
+
'group' => 'audio-video',
|
1085 |
+
'module' => 'real',
|
1086 |
+
'mime_type' => 'audio/x-realaudio',
|
1087 |
+
),
|
1088 |
+
|
1089 |
+
// SWF - audio/video - ShockWave Flash
|
1090 |
+
'swf' => array(
|
1091 |
+
'pattern' => '^(F|C)WS',
|
1092 |
+
'group' => 'audio-video',
|
1093 |
+
'module' => 'swf',
|
1094 |
+
'mime_type' => 'application/x-shockwave-flash',
|
1095 |
+
),
|
1096 |
+
|
1097 |
+
// TS - audio/video - MPEG-2 Transport Stream
|
1098 |
+
'ts' => array(
|
1099 |
+
'pattern' => '^(\\x47.{187}){10,}', // packets are 188 bytes long and start with 0x47 "G". Check for at least 10 packets matching this pattern
|
1100 |
+
'group' => 'audio-video',
|
1101 |
+
'module' => 'ts',
|
1102 |
+
'mime_type' => 'video/MP2T',
|
1103 |
+
),
|
1104 |
+
|
1105 |
+
|
1106 |
+
// Still-Image formats
|
1107 |
+
|
1108 |
+
// BMP - still image - Bitmap (Windows, OS/2; uncompressed, RLE8, RLE4)
|
1109 |
+
'bmp' => array(
|
1110 |
+
'pattern' => '^BM',
|
1111 |
+
'group' => 'graphic',
|
1112 |
+
'module' => 'bmp',
|
1113 |
+
'mime_type' => 'image/bmp',
|
1114 |
+
'fail_id3' => 'ERROR',
|
1115 |
+
'fail_ape' => 'ERROR',
|
1116 |
+
),
|
1117 |
+
|
1118 |
+
// GIF - still image - Graphics Interchange Format
|
1119 |
+
'gif' => array(
|
1120 |
+
'pattern' => '^GIF',
|
1121 |
+
'group' => 'graphic',
|
1122 |
+
'module' => 'gif',
|
1123 |
+
'mime_type' => 'image/gif',
|
1124 |
+
'fail_id3' => 'ERROR',
|
1125 |
+
'fail_ape' => 'ERROR',
|
1126 |
+
),
|
1127 |
+
|
1128 |
+
// JPEG - still image - Joint Photographic Experts Group (JPEG)
|
1129 |
+
'jpg' => array(
|
1130 |
+
'pattern' => '^\\xFF\\xD8\\xFF',
|
1131 |
+
'group' => 'graphic',
|
1132 |
+
'module' => 'jpg',
|
1133 |
+
'mime_type' => 'image/jpeg',
|
1134 |
+
'fail_id3' => 'ERROR',
|
1135 |
+
'fail_ape' => 'ERROR',
|
1136 |
+
),
|
1137 |
+
|
1138 |
+
// PCD - still image - Kodak Photo CD
|
1139 |
+
'pcd' => array(
|
1140 |
+
'pattern' => '^.{2048}PCD_IPI\\x00',
|
1141 |
+
'group' => 'graphic',
|
1142 |
+
'module' => 'pcd',
|
1143 |
+
'mime_type' => 'image/x-photo-cd',
|
1144 |
+
'fail_id3' => 'ERROR',
|
1145 |
+
'fail_ape' => 'ERROR',
|
1146 |
+
),
|
1147 |
+
|
1148 |
+
|
1149 |
+
// PNG - still image - Portable Network Graphics (PNG)
|
1150 |
+
'png' => array(
|
1151 |
+
'pattern' => '^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A',
|
1152 |
+
'group' => 'graphic',
|
1153 |
+
'module' => 'png',
|
1154 |
+
'mime_type' => 'image/png',
|
1155 |
+
'fail_id3' => 'ERROR',
|
1156 |
+
'fail_ape' => 'ERROR',
|
1157 |
+
),
|
1158 |
+
|
1159 |
+
|
1160 |
+
// SVG - still image - Scalable Vector Graphics (SVG)
|
1161 |
+
'svg' => array(
|
1162 |
+
'pattern' => '(<!DOCTYPE svg PUBLIC |xmlns="http://www\\.w3\\.org/2000/svg")',
|
1163 |
+
'group' => 'graphic',
|
1164 |
+
'module' => 'svg',
|
1165 |
+
'mime_type' => 'image/svg+xml',
|
1166 |
+
'fail_id3' => 'ERROR',
|
1167 |
+
'fail_ape' => 'ERROR',
|
1168 |
+
),
|
1169 |
+
|
1170 |
+
|
1171 |
+
// TIFF - still image - Tagged Information File Format (TIFF)
|
1172 |
+
'tiff' => array(
|
1173 |
+
'pattern' => '^(II\\x2A\\x00|MM\\x00\\x2A)',
|
1174 |
+
'group' => 'graphic',
|
1175 |
+
'module' => 'tiff',
|
1176 |
+
'mime_type' => 'image/tiff',
|
1177 |
+
'fail_id3' => 'ERROR',
|
1178 |
+
'fail_ape' => 'ERROR',
|
1179 |
+
),
|
1180 |
+
|
1181 |
+
|
1182 |
+
// EFAX - still image - eFax (TIFF derivative)
|
1183 |
+
'efax' => array(
|
1184 |
+
'pattern' => '^\\xDC\\xFE',
|
1185 |
+
'group' => 'graphic',
|
1186 |
+
'module' => 'efax',
|
1187 |
+
'mime_type' => 'image/efax',
|
1188 |
+
'fail_id3' => 'ERROR',
|
1189 |
+
'fail_ape' => 'ERROR',
|
1190 |
+
),
|
1191 |
+
|
1192 |
+
|
1193 |
+
// Data formats
|
1194 |
+
|
1195 |
+
// ISO - data - International Standards Organization (ISO) CD-ROM Image
|
1196 |
+
'iso' => array(
|
1197 |
+
'pattern' => '^.{32769}CD001',
|
1198 |
+
'group' => 'misc',
|
1199 |
+
'module' => 'iso',
|
1200 |
+
'mime_type' => 'application/octet-stream',
|
1201 |
+
'fail_id3' => 'ERROR',
|
1202 |
+
'fail_ape' => 'ERROR',
|
1203 |
+
'iconv_req' => false,
|
1204 |
+
),
|
1205 |
+
|
1206 |
+
// RAR - data - RAR compressed data
|
1207 |
+
'rar' => array(
|
1208 |
+
'pattern' => '^Rar\\!',
|
1209 |
+
'group' => 'archive',
|
1210 |
+
'module' => 'rar',
|
1211 |
+
'mime_type' => 'application/octet-stream',
|
1212 |
+
'fail_id3' => 'ERROR',
|
1213 |
+
'fail_ape' => 'ERROR',
|
1214 |
+
),
|
1215 |
+
|
1216 |
+
// SZIP - audio/data - SZIP compressed data
|
1217 |
+
'szip' => array(
|
1218 |
+
'pattern' => '^SZ\\x0A\\x04',
|
1219 |
+
'group' => 'archive',
|
1220 |
+
'module' => 'szip',
|
1221 |
+
'mime_type' => 'application/octet-stream',
|
1222 |
+
'fail_id3' => 'ERROR',
|
1223 |
+
'fail_ape' => 'ERROR',
|
1224 |
+
),
|
1225 |
+
|
1226 |
+
// TAR - data - TAR compressed data
|
1227 |
+
'tar' => array(
|
1228 |
+
'pattern' => '^.{100}[0-9\\x20]{7}\\x00[0-9\\x20]{7}\\x00[0-9\\x20]{7}\\x00[0-9\\x20\\x00]{12}[0-9\\x20\\x00]{12}',
|
1229 |
+
'group' => 'archive',
|
1230 |
+
'module' => 'tar',
|
1231 |
+
'mime_type' => 'application/x-tar',
|
1232 |
+
'fail_id3' => 'ERROR',
|
1233 |
+
'fail_ape' => 'ERROR',
|
1234 |
+
),
|
1235 |
+
|
1236 |
+
// GZIP - data - GZIP compressed data
|
1237 |
+
'gz' => array(
|
1238 |
+
'pattern' => '^\\x1F\\x8B\\x08',
|
1239 |
+
'group' => 'archive',
|
1240 |
+
'module' => 'gzip',
|
1241 |
+
'mime_type' => 'application/gzip',
|
1242 |
+
'fail_id3' => 'ERROR',
|
1243 |
+
'fail_ape' => 'ERROR',
|
1244 |
+
),
|
1245 |
+
|
1246 |
+
// ZIP - data - ZIP compressed data
|
1247 |
+
'zip' => array(
|
1248 |
+
'pattern' => '^PK\\x03\\x04',
|
1249 |
+
'group' => 'archive',
|
1250 |
+
'module' => 'zip',
|
1251 |
+
'mime_type' => 'application/zip',
|
1252 |
+
'fail_id3' => 'ERROR',
|
1253 |
+
'fail_ape' => 'ERROR',
|
1254 |
+
),
|
1255 |
+
|
1256 |
+
// XZ - data - XZ compressed data
|
1257 |
+
'xz' => array(
|
1258 |
+
'pattern' => '^\\xFD7zXZ\\x00',
|
1259 |
+
'group' => 'archive',
|
1260 |
+
'module' => 'xz',
|
1261 |
+
'mime_type' => 'application/x-xz',
|
1262 |
+
'fail_id3' => 'ERROR',
|
1263 |
+
'fail_ape' => 'ERROR',
|
1264 |
+
),
|
1265 |
+
|
1266 |
+
|
1267 |
+
// Misc other formats
|
1268 |
+
|
1269 |
+
// PAR2 - data - Parity Volume Set Specification 2.0
|
1270 |
+
'par2' => array (
|
1271 |
+
'pattern' => '^PAR2\\x00PKT',
|
1272 |
+
'group' => 'misc',
|
1273 |
+
'module' => 'par2',
|
1274 |
+
'mime_type' => 'application/octet-stream',
|
1275 |
+
'fail_id3' => 'ERROR',
|
1276 |
+
'fail_ape' => 'ERROR',
|
1277 |
+
),
|
1278 |
+
|
1279 |
+
// PDF - data - Portable Document Format
|
1280 |
+
'pdf' => array(
|
1281 |
+
'pattern' => '^\\x25PDF',
|
1282 |
+
'group' => 'misc',
|
1283 |
+
'module' => 'pdf',
|
1284 |
+
'mime_type' => 'application/pdf',
|
1285 |
+
'fail_id3' => 'ERROR',
|
1286 |
+
'fail_ape' => 'ERROR',
|
1287 |
+
),
|
1288 |
+
|
1289 |
+
// MSOFFICE - data - ZIP compressed data
|
1290 |
+
'msoffice' => array(
|
1291 |
+
'pattern' => '^\\xD0\\xCF\\x11\\xE0\\xA1\\xB1\\x1A\\xE1', // D0CF11E == DOCFILE == Microsoft Office Document
|
1292 |
+
'group' => 'misc',
|
1293 |
+
'module' => 'msoffice',
|
1294 |
+
'mime_type' => 'application/octet-stream',
|
1295 |
+
'fail_id3' => 'ERROR',
|
1296 |
+
'fail_ape' => 'ERROR',
|
1297 |
+
),
|
1298 |
+
|
1299 |
+
// CUE - data - CUEsheet (index to single-file disc images)
|
1300 |
+
'cue' => array(
|
1301 |
+
'pattern' => '', // empty pattern means cannot be automatically detected, will fall through all other formats and match based on filename and very basic file contents
|
1302 |
+
'group' => 'misc',
|
1303 |
+
'module' => 'cue',
|
1304 |
+
'mime_type' => 'application/octet-stream',
|
1305 |
+
),
|
1306 |
+
|
1307 |
+
);
|
1308 |
}
|
1309 |
|
1310 |
+
return $format_info;
|
1311 |
+
}
|
1312 |
|
1313 |
+
/**
|
1314 |
+
* @param string $filedata
|
1315 |
+
* @param string $filename
|
1316 |
+
*
|
1317 |
+
* @return mixed|false
|
1318 |
+
*/
|
1319 |
+
public function GetFileFormat(&$filedata, $filename='') {
|
1320 |
+
// this function will determine the format of a file based on usually
|
1321 |
+
// the first 2-4 bytes of the file (8 bytes for PNG, 16 bytes for JPG,
|
1322 |
+
// and in the case of ISO CD image, 6 bytes offset 32kb from the start
|
1323 |
+
// of the file).
|
1324 |
+
|
1325 |
+
// Identify file format - loop through $format_info and detect with reg expr
|
1326 |
+
foreach ($this->GetFileFormatArray() as $format_name => $info) {
|
1327 |
+
// The /s switch on preg_match() forces preg_match() NOT to treat
|
1328 |
+
// newline (0x0A) characters as special chars but do a binary match
|
1329 |
+
if (!empty($info['pattern']) && preg_match('#'.$info['pattern'].'#s', $filedata)) {
|
|
|
|
|
|
|
|
|
|
|
|
|
1330 |
$info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php';
|
1331 |
return $info;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1332 |
}
|
|
|
|
|
1333 |
}
|
1334 |
|
1335 |
|
1336 |
+
if (preg_match('#\\.mp[123a]$#i', $filename)) {
|
1337 |
+
// Too many mp3 encoders on the market put garbage in front of mpeg files
|
1338 |
+
// use assume format on these if format detection failed
|
1339 |
+
$GetFileFormatArray = $this->GetFileFormatArray();
|
1340 |
+
$info = $GetFileFormatArray['mp3'];
|
1341 |
+
$info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php';
|
1342 |
+
return $info;
|
1343 |
+
} elseif (preg_match('#\\.cue$#i', $filename) && preg_match('#FILE "[^"]+" (BINARY|MOTOROLA|AIFF|WAVE|MP3)#', $filedata)) {
|
1344 |
+
// there's not really a useful consistent "magic" at the beginning of .cue files to identify them
|
1345 |
+
// so until I think of something better, just go by filename if all other format checks fail
|
1346 |
+
// and verify there's at least one instance of "TRACK xx AUDIO" in the file
|
1347 |
+
$GetFileFormatArray = $this->GetFileFormatArray();
|
1348 |
+
$info = $GetFileFormatArray['cue'];
|
1349 |
+
$info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php';
|
1350 |
+
return $info;
|
1351 |
+
}
|
1352 |
|
1353 |
+
return false;
|
1354 |
+
}
|
|
|
|
|
1355 |
|
1356 |
+
/**
|
1357 |
+
* Converts array to $encoding charset from $this->encoding.
|
1358 |
+
*
|
1359 |
+
* @param array $array
|
1360 |
+
* @param string $encoding
|
1361 |
+
*/
|
1362 |
+
public function CharConvert(&$array, $encoding) {
|
1363 |
+
|
1364 |
+
// identical encoding - end here
|
1365 |
+
if ($encoding == $this->encoding) {
|
1366 |
+
return;
|
1367 |
+
}
|
1368 |
|
1369 |
+
// loop thru array
|
1370 |
+
foreach ($array as $key => $value) {
|
|
|
|
|
1371 |
|
1372 |
+
// go recursive
|
1373 |
+
if (is_array($value)) {
|
1374 |
+
$this->CharConvert($array[$key], $encoding);
|
|
|
1375 |
}
|
|
|
1376 |
|
1377 |
+
// convert string
|
1378 |
+
elseif (is_string($value)) {
|
1379 |
+
$array[$key] = trim(getid3_lib::iconv_fallback($encoding, $this->encoding, $value));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1380 |
}
|
1381 |
+
}
|
1382 |
+
}
|
1383 |
|
1384 |
+
/**
|
1385 |
+
* @return bool
|
1386 |
+
*/
|
1387 |
+
public function HandleAllTags() {
|
1388 |
+
|
1389 |
+
// key name => array (tag name, character encoding)
|
1390 |
+
static $tags;
|
1391 |
+
if (empty($tags)) {
|
1392 |
+
$tags = array(
|
1393 |
+
'asf' => array('asf' , 'UTF-16LE'),
|
1394 |
+
'midi' => array('midi' , 'ISO-8859-1'),
|
1395 |
+
'nsv' => array('nsv' , 'ISO-8859-1'),
|
1396 |
+
'ogg' => array('vorbiscomment' , 'UTF-8'),
|
1397 |
+
'png' => array('png' , 'UTF-8'),
|
1398 |
+
'tiff' => array('tiff' , 'ISO-8859-1'),
|
1399 |
+
'quicktime' => array('quicktime' , 'UTF-8'),
|
1400 |
+
'real' => array('real' , 'ISO-8859-1'),
|
1401 |
+
'vqf' => array('vqf' , 'ISO-8859-1'),
|
1402 |
+
'zip' => array('zip' , 'ISO-8859-1'),
|
1403 |
+
'riff' => array('riff' , 'ISO-8859-1'),
|
1404 |
+
'lyrics3' => array('lyrics3' , 'ISO-8859-1'),
|
1405 |
+
'id3v1' => array('id3v1' , $this->encoding_id3v1),
|
1406 |
+
'id3v2' => array('id3v2' , 'UTF-8'), // not according to the specs (every frame can have a different encoding), but getID3() force-converts all encodings to UTF-8
|
1407 |
+
'ape' => array('ape' , 'UTF-8'),
|
1408 |
+
'cue' => array('cue' , 'ISO-8859-1'),
|
1409 |
+
'matroska' => array('matroska' , 'UTF-8'),
|
1410 |
+
'flac' => array('vorbiscomment' , 'UTF-8'),
|
1411 |
+
'divxtag' => array('divx' , 'ISO-8859-1'),
|
1412 |
+
'iptc' => array('iptc' , 'ISO-8859-1'),
|
1413 |
+
);
|
1414 |
+
}
|
1415 |
|
1416 |
+
// loop through comments array
|
1417 |
+
foreach ($tags as $comment_name => $tagname_encoding_array) {
|
1418 |
+
list($tag_name, $encoding) = $tagname_encoding_array;
|
|
|
1419 |
|
1420 |
+
// fill in default encoding type if not already present
|
1421 |
+
if (isset($this->info[$comment_name]) && !isset($this->info[$comment_name]['encoding'])) {
|
1422 |
+
$this->info[$comment_name]['encoding'] = $encoding;
|
1423 |
+
}
|
1424 |
+
|
1425 |
+
// copy comments if key name set
|
1426 |
+
if (!empty($this->info[$comment_name]['comments'])) {
|
1427 |
+
foreach ($this->info[$comment_name]['comments'] as $tag_key => $valuearray) {
|
1428 |
+
foreach ($valuearray as $key => $value) {
|
1429 |
+
if (is_string($value)) {
|
1430 |
+
$value = trim($value, " \r\n\t"); // do not trim nulls from $value!! Unicode characters will get mangled if trailing nulls are removed!
|
|
|
|
|
|
|
1431 |
}
|
1432 |
+
if ($value) {
|
1433 |
+
if (!is_numeric($key)) {
|
1434 |
+
$this->info['tags'][trim($tag_name)][trim($tag_key)][$key] = $value;
|
1435 |
+
} else {
|
1436 |
+
$this->info['tags'][trim($tag_name)][trim($tag_key)][] = $value;
|
1437 |
+
}
|
1438 |
}
|
1439 |
}
|
1440 |
+
if ($tag_key == 'picture') {
|
1441 |
+
// pictures can take up a lot of space, and we don't need multiple copies of them; let there be a single copy in [comments][picture], and not elsewhere
|
1442 |
+
unset($this->info[$comment_name]['comments'][$tag_key]);
|
|
|
1443 |
}
|
1444 |
+
}
|
1445 |
|
1446 |
+
if (!isset($this->info['tags'][$tag_name])) {
|
1447 |
+
// comments are set but contain nothing but empty strings, so skip
|
1448 |
+
continue;
|
1449 |
+
}
|
|
|
1450 |
|
1451 |
+
$this->CharConvert($this->info['tags'][$tag_name], $this->info[$comment_name]['encoding']); // only copy gets converted!
|
1452 |
+
|
1453 |
+
if ($this->option_tags_html) {
|
1454 |
+
foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) {
|
1455 |
+
if ($tag_key == 'picture') {
|
1456 |
+
// Do not to try to convert binary picture data to HTML
|
1457 |
+
// https://github.com/JamesHeinrich/getID3/issues/178
|
1458 |
+
continue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1459 |
}
|
1460 |
+
$this->info['tags_html'][$tag_name][$tag_key] = getid3_lib::recursiveMultiByteCharString2HTML($valuearray, $this->info[$comment_name]['encoding']);
|
1461 |
}
|
|
|
|
|
|
|
1462 |
}
|
1463 |
|
1464 |
}
|
1465 |
|
1466 |
+
}
|
1467 |
+
|
1468 |
+
// pictures can take up a lot of space, and we don't need multiple copies of them; let there be a single copy in [comments][picture], and not elsewhere
|
1469 |
+
if (!empty($this->info['tags'])) {
|
1470 |
+
$unset_keys = array('tags', 'tags_html');
|
1471 |
+
foreach ($this->info['tags'] as $tagtype => $tagarray) {
|
1472 |
+
foreach ($tagarray as $tagname => $tagdata) {
|
1473 |
+
if ($tagname == 'picture') {
|
1474 |
+
foreach ($tagdata as $key => $tagarray) {
|
1475 |
+
$this->info['comments']['picture'][] = $tagarray;
|
1476 |
+
if (isset($tagarray['data']) && isset($tagarray['image_mime'])) {
|
1477 |
+
if (isset($this->info['tags'][$tagtype][$tagname][$key])) {
|
1478 |
+
unset($this->info['tags'][$tagtype][$tagname][$key]);
|
1479 |
+
}
|
1480 |
+
if (isset($this->info['tags_html'][$tagtype][$tagname][$key])) {
|
1481 |
+
unset($this->info['tags_html'][$tagtype][$tagname][$key]);
|
1482 |
}
|
1483 |
}
|
1484 |
}
|
1485 |
}
|
1486 |
+
}
|
1487 |
+
foreach ($unset_keys as $unset_key) {
|
1488 |
+
// remove possible empty keys from (e.g. [tags][id3v2][picture])
|
1489 |
+
if (empty($this->info[$unset_key][$tagtype]['picture'])) {
|
1490 |
+
unset($this->info[$unset_key][$tagtype]['picture']);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1491 |
}
|
1492 |
+
if (empty($this->info[$unset_key][$tagtype])) {
|
1493 |
+
unset($this->info[$unset_key][$tagtype]);
|
1494 |
}
|
1495 |
+
if (empty($this->info[$unset_key])) {
|
1496 |
+
unset($this->info[$unset_key]);
|
1497 |
}
|
1498 |
}
|
1499 |
+
// remove duplicate copy of picture data from (e.g. [id3v2][comments][picture])
|
1500 |
+
if (isset($this->info[$tagtype]['comments']['picture'])) {
|
1501 |
+
unset($this->info[$tagtype]['comments']['picture']);
|
1502 |
+
}
|
1503 |
+
if (empty($this->info[$tagtype]['comments'])) {
|
1504 |
+
unset($this->info[$tagtype]['comments']);
|
1505 |
+
}
|
1506 |
+
if (empty($this->info[$tagtype])) {
|
1507 |
+
unset($this->info[$tagtype]);
|
1508 |
+
}
|
1509 |
}
|
|
|
1510 |
}
|
1511 |
+
return true;
|
1512 |
+
}
|
1513 |
|
1514 |
+
/**
|
1515 |
+
* @param string $algorithm
|
1516 |
+
*
|
1517 |
+
* @return array|bool
|
1518 |
+
*/
|
1519 |
+
public function getHashdata($algorithm) {
|
1520 |
+
switch ($algorithm) {
|
1521 |
+
case 'md5':
|
1522 |
+
case 'sha1':
|
1523 |
+
break;
|
1524 |
+
|
1525 |
+
default:
|
1526 |
+
return $this->error('bad algorithm "'.$algorithm.'" in getHashdata()');
|
1527 |
+
break;
|
1528 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1529 |
|
1530 |
+
if (!empty($this->info['fileformat']) && !empty($this->info['dataformat']) && ($this->info['fileformat'] == 'ogg') && ($this->info['audio']['dataformat'] == 'vorbis')) {
|
1531 |
+
|
1532 |
+
// We cannot get an identical md5_data value for Ogg files where the comments
|
1533 |
+
// span more than 1 Ogg page (compared to the same audio data with smaller
|
1534 |
+
// comments) using the normal getID3() method of MD5'ing the data between the
|
1535 |
+
// end of the comments and the end of the file (minus any trailing tags),
|
1536 |
+
// because the page sequence numbers of the pages that the audio data is on
|
1537 |
+
// do not match. Under normal circumstances, where comments are smaller than
|
1538 |
+
// the nominal 4-8kB page size, then this is not a problem, but if there are
|
1539 |
+
// very large comments, the only way around it is to strip off the comment
|
1540 |
+
// tags with vorbiscomment and MD5 that file.
|
1541 |
+
// This procedure must be applied to ALL Ogg files, not just the ones with
|
1542 |
+
// comments larger than 1 page, because the below method simply MD5's the
|
1543 |
+
// whole file with the comments stripped, not just the portion after the
|
1544 |
+
// comments block (which is the standard getID3() method.
|
1545 |
+
|
1546 |
+
// The above-mentioned problem of comments spanning multiple pages and changing
|
1547 |
+
// page sequence numbers likely happens for OggSpeex and OggFLAC as well, but
|
1548 |
+
// currently vorbiscomment only works on OggVorbis files.
|
1549 |
|
1550 |
+
if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) {
|
|
|
|
|
1551 |
|
1552 |
+
$this->warning('Failed making system call to vorbiscomment.exe - '.$algorithm.'_data is incorrect - error returned: PHP running in Safe Mode (backtick operator not available)');
|
1553 |
+
$this->info[$algorithm.'_data'] = false;
|
1554 |
|
1555 |
+
} else {
|
1556 |
|
1557 |
+
// Prevent user from aborting script
|
1558 |
+
$old_abort = ignore_user_abort(true);
|
1559 |
|
1560 |
+
// Create empty file
|
1561 |
+
$empty = tempnam(GETID3_TEMP_DIR, 'getID3');
|
1562 |
+
touch($empty);
|
1563 |
|
1564 |
+
// Use vorbiscomment to make temp file without comments
|
1565 |
+
$temp = tempnam(GETID3_TEMP_DIR, 'getID3');
|
1566 |
+
$file = $this->info['filenamepath'];
|
1567 |
|
1568 |
+
if (GETID3_OS_ISWINDOWS) {
|
1569 |
|
1570 |
+
if (file_exists(GETID3_HELPERAPPSDIR.'vorbiscomment.exe')) {
|
1571 |
|
1572 |
+
$commandline = '"'.GETID3_HELPERAPPSDIR.'vorbiscomment.exe" -w -c "'.$empty.'" "'.$file.'" "'.$temp.'"';
|
|
|
1573 |
$VorbisCommentError = `$commandline`;
|
1574 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1575 |
} else {
|
1576 |
|
1577 |
+
$VorbisCommentError = 'vorbiscomment.exe not found in '.GETID3_HELPERAPPSDIR;
|
|
|
|
|
|
|
|
|
1578 |
|
|
|
|
|
|
|
|
|
1579 |
}
|
1580 |
|
1581 |
+
} else {
|
|
|
|
|
1582 |
|
1583 |
+
$commandline = 'vorbiscomment -w -c '.escapeshellarg($empty).' '.escapeshellarg($file).' '.escapeshellarg($temp).' 2>&1';
|
1584 |
+
$VorbisCommentError = `$commandline`;
|
1585 |
|
1586 |
}
|
1587 |
|
1588 |
+
if (!empty($VorbisCommentError)) {
|
|
|
|
|
1589 |
|
1590 |
+
$this->warning('Failed making system call to vorbiscomment(.exe) - '.$algorithm.'_data will be incorrect. If vorbiscomment is unavailable, please download from http://www.vorbis.com/download.psp and put in the getID3() directory. Error returned: '.$VorbisCommentError);
|
1591 |
+
$this->info[$algorithm.'_data'] = false;
|
1592 |
|
1593 |
} else {
|
1594 |
|
1595 |
+
// Get hash of newly created file
|
1596 |
switch ($algorithm) {
|
1597 |
case 'md5':
|
1598 |
+
$this->info[$algorithm.'_data'] = md5_file($temp);
|
1599 |
break;
|
1600 |
|
1601 |
case 'sha1':
|
1602 |
+
$this->info[$algorithm.'_data'] = sha1_file($temp);
|
1603 |
break;
|
1604 |
}
|
1605 |
}
|
1606 |
|
1607 |
+
// Clean up
|
1608 |
+
unlink($empty);
|
1609 |
+
unlink($temp);
|
1610 |
+
|
1611 |
+
// Reset abort setting
|
1612 |
+
ignore_user_abort($old_abort);
|
1613 |
+
|
1614 |
}
|
|
|
|
|
1615 |
|
1616 |
+
} else {
|
1617 |
|
1618 |
+
if (!empty($this->info['avdataoffset']) || (isset($this->info['avdataend']) && ($this->info['avdataend'] < $this->info['filesize']))) {
|
1619 |
|
1620 |
+
// get hash from part of file
|
1621 |
+
$this->info[$algorithm.'_data'] = getid3_lib::hash_data($this->info['filenamepath'], $this->info['avdataoffset'], $this->info['avdataend'], $algorithm);
|
|
|
|
|
|
|
|
|
|
|
|
|
1622 |
|
1623 |
+
} else {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1624 |
|
1625 |
+
// get hash from whole file
|
1626 |
+
switch ($algorithm) {
|
1627 |
+
case 'md5':
|
1628 |
+
$this->info[$algorithm.'_data'] = md5_file($this->info['filenamepath']);
|
1629 |
+
break;
|
1630 |
|
1631 |
+
case 'sha1':
|
1632 |
+
$this->info[$algorithm.'_data'] = sha1_file($this->info['filenamepath']);
|
1633 |
+
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1634 |
}
|
1635 |
}
|
1636 |
|
|
|
|
|
|
|
|
|
1637 |
}
|
1638 |
+
return true;
|
1639 |
+
}
|
1640 |
|
1641 |
+
public function ChannelsBitratePlaytimeCalculations() {
|
1642 |
|
1643 |
+
// set channelmode on audio
|
1644 |
+
if (!empty($this->info['audio']['channelmode']) || !isset($this->info['audio']['channels'])) {
|
1645 |
+
// ignore
|
1646 |
+
} elseif ($this->info['audio']['channels'] == 1) {
|
1647 |
+
$this->info['audio']['channelmode'] = 'mono';
|
1648 |
+
} elseif ($this->info['audio']['channels'] == 2) {
|
1649 |
+
$this->info['audio']['channelmode'] = 'stereo';
|
1650 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1651 |
|
1652 |
+
// Calculate combined bitrate - audio + video
|
1653 |
+
$CombinedBitrate = 0;
|
1654 |
+
$CombinedBitrate += (isset($this->info['audio']['bitrate']) ? $this->info['audio']['bitrate'] : 0);
|
1655 |
+
$CombinedBitrate += (isset($this->info['video']['bitrate']) ? $this->info['video']['bitrate'] : 0);
|
1656 |
+
if (($CombinedBitrate > 0) && empty($this->info['bitrate'])) {
|
1657 |
+
$this->info['bitrate'] = $CombinedBitrate;
|
1658 |
+
}
|
1659 |
+
//if ((isset($this->info['video']) && !isset($this->info['video']['bitrate'])) || (isset($this->info['audio']) && !isset($this->info['audio']['bitrate']))) {
|
1660 |
+
// // for example, VBR MPEG video files cannot determine video bitrate:
|
1661 |
+
// // should not set overall bitrate and playtime from audio bitrate only
|
1662 |
+
// unset($this->info['bitrate']);
|
1663 |
+
//}
|
1664 |
+
|
1665 |
+
// video bitrate undetermined, but calculable
|
1666 |
+
if (isset($this->info['video']['dataformat']) && $this->info['video']['dataformat'] && (!isset($this->info['video']['bitrate']) || ($this->info['video']['bitrate'] == 0))) {
|
1667 |
+
// if video bitrate not set
|
1668 |
+
if (isset($this->info['audio']['bitrate']) && ($this->info['audio']['bitrate'] > 0) && ($this->info['audio']['bitrate'] == $this->info['bitrate'])) {
|
1669 |
+
// AND if audio bitrate is set to same as overall bitrate
|
1670 |
+
if (isset($this->info['playtime_seconds']) && ($this->info['playtime_seconds'] > 0)) {
|
1671 |
+
// AND if playtime is set
|
1672 |
+
if (isset($this->info['avdataend']) && isset($this->info['avdataoffset'])) {
|
1673 |
+
// AND if AV data offset start/end is known
|
1674 |
+
// THEN we can calculate the video bitrate
|
1675 |
+
$this->info['bitrate'] = round((($this->info['avdataend'] - $this->info['avdataoffset']) * 8) / $this->info['playtime_seconds']);
|
1676 |
+
$this->info['video']['bitrate'] = $this->info['bitrate'] - $this->info['audio']['bitrate'];
|
1677 |
}
|
1678 |
+
}
|
1679 |
}
|
|
|
|
|
|
|
|
|
1680 |
}
|
1681 |
|
1682 |
+
if ((!isset($this->info['playtime_seconds']) || ($this->info['playtime_seconds'] <= 0)) && !empty($this->info['bitrate'])) {
|
1683 |
+
$this->info['playtime_seconds'] = (($this->info['avdataend'] - $this->info['avdataoffset']) * 8) / $this->info['bitrate'];
|
1684 |
+
}
|
1685 |
|
1686 |
+
if (!isset($this->info['bitrate']) && !empty($this->info['playtime_seconds'])) {
|
1687 |
+
$this->info['bitrate'] = (($this->info['avdataend'] - $this->info['avdataoffset']) * 8) / $this->info['playtime_seconds'];
|
1688 |
+
}
|
1689 |
+
if (isset($this->info['bitrate']) && empty($this->info['audio']['bitrate']) && empty($this->info['video']['bitrate'])) {
|
1690 |
+
if (isset($this->info['audio']['dataformat']) && empty($this->info['video']['resolution_x'])) {
|
1691 |
+
// audio only
|
1692 |
+
$this->info['audio']['bitrate'] = $this->info['bitrate'];
|
1693 |
+
} elseif (isset($this->info['video']['resolution_x']) && empty($this->info['audio']['dataformat'])) {
|
1694 |
+
// video only
|
1695 |
+
$this->info['video']['bitrate'] = $this->info['bitrate'];
|
1696 |
}
|
1697 |
+
}
|
1698 |
|
1699 |
+
// Set playtime string
|
1700 |
+
if (!empty($this->info['playtime_seconds']) && empty($this->info['playtime_string'])) {
|
1701 |
+
$this->info['playtime_string'] = getid3_lib::PlaytimeString($this->info['playtime_seconds']);
|
|
|
|
|
|
|
|
|
|
|
1702 |
}
|
1703 |
+
}
|
1704 |
|
1705 |
+
/**
|
1706 |
+
* @return bool
|
1707 |
+
*/
|
1708 |
+
public function CalculateCompressionRatioVideo() {
|
1709 |
+
if (empty($this->info['video'])) {
|
1710 |
+
return false;
|
1711 |
+
}
|
1712 |
+
if (empty($this->info['video']['resolution_x']) || empty($this->info['video']['resolution_y'])) {
|
1713 |
+
return false;
|
1714 |
+
}
|
1715 |
+
if (empty($this->info['video']['bits_per_sample'])) {
|
1716 |
+
return false;
|
1717 |
+
}
|
1718 |
|
1719 |
+
switch ($this->info['video']['dataformat']) {
|
1720 |
+
case 'bmp':
|
1721 |
+
case 'gif':
|
1722 |
+
case 'jpeg':
|
1723 |
+
case 'jpg':
|
1724 |
+
case 'png':
|
1725 |
+
case 'tiff':
|
1726 |
+
$FrameRate = 1;
|
1727 |
+
$PlaytimeSeconds = 1;
|
1728 |
+
$BitrateCompressed = $this->info['filesize'] * 8;
|
1729 |
+
break;
|
1730 |
+
|
1731 |
+
default:
|
1732 |
+
if (!empty($this->info['video']['frame_rate'])) {
|
1733 |
+
$FrameRate = $this->info['video']['frame_rate'];
|
1734 |
+
} else {
|
1735 |
+
return false;
|
1736 |
}
|
1737 |
+
if (!empty($this->info['playtime_seconds'])) {
|
1738 |
+
$PlaytimeSeconds = $this->info['playtime_seconds'];
|
1739 |
+
} else {
|
1740 |
+
return false;
|
1741 |
}
|
1742 |
+
if (!empty($this->info['video']['bitrate'])) {
|
1743 |
+
$BitrateCompressed = $this->info['video']['bitrate'];
|
1744 |
+
} else {
|
1745 |
+
return false;
|
1746 |
}
|
1747 |
+
break;
|
1748 |
+
}
|
1749 |
+
$BitrateUncompressed = $this->info['video']['resolution_x'] * $this->info['video']['resolution_y'] * $this->info['video']['bits_per_sample'] * $FrameRate;
|
1750 |
|
1751 |
+
$this->info['video']['compression_ratio'] = $BitrateCompressed / $BitrateUncompressed;
|
1752 |
+
return true;
|
1753 |
+
}
|
1754 |
+
|
1755 |
+
/**
|
1756 |
+
* @return bool
|
1757 |
+
*/
|
1758 |
+
public function CalculateCompressionRatioAudio() {
|
1759 |
+
if (empty($this->info['audio']['bitrate']) || empty($this->info['audio']['channels']) || empty($this->info['audio']['sample_rate']) || !is_numeric($this->info['audio']['sample_rate'])) {
|
1760 |
+
return false;
|
1761 |
}
|
1762 |
+
$this->info['audio']['compression_ratio'] = $this->info['audio']['bitrate'] / ($this->info['audio']['channels'] * $this->info['audio']['sample_rate'] * (!empty($this->info['audio']['bits_per_sample']) ? $this->info['audio']['bits_per_sample'] : 16));
|
1763 |
|
1764 |
+
if (!empty($this->info['audio']['streams'])) {
|
1765 |
+
foreach ($this->info['audio']['streams'] as $streamnumber => $streamdata) {
|
1766 |
+
if (!empty($streamdata['bitrate']) && !empty($streamdata['channels']) && !empty($streamdata['sample_rate'])) {
|
1767 |
+
$this->info['audio']['streams'][$streamnumber]['compression_ratio'] = $streamdata['bitrate'] / ($streamdata['channels'] * $streamdata['sample_rate'] * (!empty($streamdata['bits_per_sample']) ? $streamdata['bits_per_sample'] : 16));
|
|
|
|
|
|
|
|
|
1768 |
}
|
1769 |
}
|
|
|
1770 |
}
|
1771 |
+
return true;
|
1772 |
+
}
|
1773 |
|
1774 |
+
/**
|
1775 |
+
* @return bool
|
1776 |
+
*/
|
1777 |
+
public function CalculateReplayGain() {
|
1778 |
+
if (isset($this->info['replay_gain'])) {
|
1779 |
+
if (!isset($this->info['replay_gain']['reference_volume'])) {
|
1780 |
+
$this->info['replay_gain']['reference_volume'] = 89.0;
|
1781 |
+
}
|
1782 |
+
if (isset($this->info['replay_gain']['track']['adjustment'])) {
|
1783 |
+
$this->info['replay_gain']['track']['volume'] = $this->info['replay_gain']['reference_volume'] - $this->info['replay_gain']['track']['adjustment'];
|
1784 |
+
}
|
1785 |
+
if (isset($this->info['replay_gain']['album']['adjustment'])) {
|
1786 |
+
$this->info['replay_gain']['album']['volume'] = $this->info['replay_gain']['reference_volume'] - $this->info['replay_gain']['album']['adjustment'];
|
1787 |
+
}
|
1788 |
|
1789 |
+
if (isset($this->info['replay_gain']['track']['peak'])) {
|
1790 |
+
$this->info['replay_gain']['track']['max_noclip_gain'] = 0 - getid3_lib::RGADamplitude2dB($this->info['replay_gain']['track']['peak']);
|
1791 |
+
}
|
1792 |
+
if (isset($this->info['replay_gain']['album']['peak'])) {
|
1793 |
+
$this->info['replay_gain']['album']['max_noclip_gain'] = 0 - getid3_lib::RGADamplitude2dB($this->info['replay_gain']['album']['peak']);
|
1794 |
}
|
|
|
|
|
1795 |
}
|
1796 |
+
return true;
|
1797 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1798 |
|
1799 |
+
/**
|
1800 |
+
* @return bool
|
1801 |
+
*/
|
1802 |
+
public function ProcessAudioStreams() {
|
1803 |
+
if (!empty($this->info['audio']['bitrate']) || !empty($this->info['audio']['channels']) || !empty($this->info['audio']['sample_rate'])) {
|
1804 |
+
if (!isset($this->info['audio']['streams'])) {
|
1805 |
+
foreach ($this->info['audio'] as $key => $value) {
|
1806 |
+
if ($key != 'streams') {
|
1807 |
+
$this->info['audio']['streams'][0][$key] = $value;
|
1808 |
+
}
|
1809 |
+
}
|
1810 |
}
|
1811 |
}
|
1812 |
+
return true;
|
1813 |
+
}
|
1814 |
|
1815 |
+
/**
|
1816 |
+
* @return string|bool
|
1817 |
+
*/
|
1818 |
+
public function getid3_tempnam() {
|
1819 |
+
return tempnam($this->tempdir, 'gI3');
|
1820 |
+
}
|
1821 |
|
1822 |
+
/**
|
1823 |
+
* @param string $name
|
1824 |
+
*
|
1825 |
+
* @return bool
|
1826 |
+
*
|
1827 |
+
* @throws getid3_exception
|
1828 |
+
*/
|
1829 |
+
public function include_module($name) {
|
1830 |
+
//if (!file_exists($this->include_path.'module.'.$name.'.php')) {
|
1831 |
+
if (!file_exists(GETID3_INCLUDEPATH.'module.'.$name.'.php')) {
|
1832 |
+
throw new getid3_exception('Required module.'.$name.'.php is missing.');
|
1833 |
+
}
|
1834 |
+
include_once(GETID3_INCLUDEPATH.'module.'.$name.'.php');
|
1835 |
+
return true;
|
1836 |
+
}
|
1837 |
|
1838 |
+
/**
|
1839 |
+
* @param string $filename
|
1840 |
+
*
|
1841 |
+
* @return bool
|
1842 |
+
*/
|
1843 |
+
public static function is_writable ($filename) {
|
1844 |
+
$ret = is_writable($filename);
|
1845 |
+
if (!$ret) {
|
1846 |
+
$perms = fileperms($filename);
|
1847 |
+
$ret = ($perms & 0x0080) || ($perms & 0x0010) || ($perms & 0x0002);
|
1848 |
+
}
|
1849 |
+
return $ret;
|
1850 |
+
}
|
1851 |
|
1852 |
+
}
|
|
|
|
|
|
|
1853 |
|
|
|
|
|
|
|
|
|
1854 |
|
1855 |
+
abstract class getid3_handler
|
1856 |
+
{
|
1857 |
+
|
1858 |
+
/**
|
1859 |
+
* @var getID3
|
1860 |
+
*/
|
1861 |
+
protected $getid3; // pointer
|
1862 |
+
|
1863 |
+
/**
|
1864 |
+
* Analyzing filepointer or string.
|
1865 |
+
*
|
1866 |
+
* @var bool
|
1867 |
+
*/
|
1868 |
+
protected $data_string_flag = false;
|
1869 |
+
|
1870 |
+
/**
|
1871 |
+
* String to analyze.
|
1872 |
+
*
|
1873 |
+
* @var string
|
1874 |
+
*/
|
1875 |
+
protected $data_string = '';
|
1876 |
+
|
1877 |
+
/**
|
1878 |
+
* Seek position in string.
|
1879 |
+
*
|
1880 |
+
* @var int
|
1881 |
+
*/
|
1882 |
+
protected $data_string_position = 0;
|
1883 |
+
|
1884 |
+
/**
|
1885 |
+
* String length.
|
1886 |
+
*
|
1887 |
+
* @var int
|
1888 |
+
*/
|
1889 |
+
protected $data_string_length = 0;
|
1890 |
+
|
1891 |
+
/**
|
1892 |
+
* @var string
|
1893 |
+
*/
|
1894 |
+
private $dependency_to;
|
1895 |
+
|
1896 |
+
/**
|
1897 |
+
* getid3_handler constructor.
|
1898 |
+
*
|
1899 |
+
* @param getID3 $getid3
|
1900 |
+
* @param string $call_module
|
1901 |
+
*/
|
1902 |
+
public function __construct(getID3 $getid3, $call_module=null) {
|
1903 |
+
$this->getid3 = $getid3;
|
1904 |
+
|
1905 |
+
if ($call_module) {
|
1906 |
+
$this->dependency_to = str_replace('getid3_', '', $call_module);
|
1907 |
+
}
|
1908 |
+
}
|
1909 |
|
1910 |
+
/**
|
1911 |
+
* Analyze from file pointer.
|
1912 |
+
*
|
1913 |
+
* @return bool
|
1914 |
+
*/
|
1915 |
+
abstract public function Analyze();
|
1916 |
+
|
1917 |
+
/**
|
1918 |
+
* Analyze from string instead.
|
1919 |
+
*
|
1920 |
+
* @param string $string
|
1921 |
+
*/
|
1922 |
+
public function AnalyzeString($string) {
|
1923 |
+
// Enter string mode
|
1924 |
+
$this->setStringMode($string);
|
1925 |
+
|
1926 |
+
// Save info
|
1927 |
+
$saved_avdataoffset = $this->getid3->info['avdataoffset'];
|
1928 |
+
$saved_avdataend = $this->getid3->info['avdataend'];
|
1929 |
+
$saved_filesize = (isset($this->getid3->info['filesize']) ? $this->getid3->info['filesize'] : null); // may be not set if called as dependency without openfile() call
|
1930 |
+
|
1931 |
+
// Reset some info
|
1932 |
+
$this->getid3->info['avdataoffset'] = 0;
|
1933 |
+
$this->getid3->info['avdataend'] = $this->getid3->info['filesize'] = $this->data_string_length;
|
1934 |
+
|
1935 |
+
// Analyze
|
1936 |
+
$this->Analyze();
|
1937 |
+
|
1938 |
+
// Restore some info
|
1939 |
+
$this->getid3->info['avdataoffset'] = $saved_avdataoffset;
|
1940 |
+
$this->getid3->info['avdataend'] = $saved_avdataend;
|
1941 |
+
$this->getid3->info['filesize'] = $saved_filesize;
|
1942 |
+
|
1943 |
+
// Exit string mode
|
1944 |
+
$this->data_string_flag = false;
|
1945 |
+
}
|
1946 |
|
1947 |
+
/**
|
1948 |
+
* @param string $string
|
1949 |
+
*/
|
1950 |
+
public function setStringMode($string) {
|
1951 |
+
$this->data_string_flag = true;
|
1952 |
+
$this->data_string = $string;
|
1953 |
+
$this->data_string_length = strlen($string);
|
1954 |
+
}
|
1955 |
|
1956 |
+
/**
|
1957 |
+
* @return int|bool
|
1958 |
+
*/
|
1959 |
+
protected function ftell() {
|
1960 |
+
if ($this->data_string_flag) {
|
1961 |
+
return $this->data_string_position;
|
1962 |
}
|
1963 |
+
return ftell($this->getid3->fp);
|
1964 |
+
}
|
1965 |
|
1966 |
+
/**
|
1967 |
+
* @param int $bytes
|
1968 |
+
*
|
1969 |
+
* @return string|false
|
1970 |
+
*
|
1971 |
+
* @throws getid3_exception
|
1972 |
+
*/
|
1973 |
+
protected function fread($bytes) {
|
1974 |
+
if ($this->data_string_flag) {
|
1975 |
+
$this->data_string_position += $bytes;
|
1976 |
+
return substr($this->data_string, $this->data_string_position - $bytes, $bytes);
|
1977 |
}
|
1978 |
+
$pos = $this->ftell() + $bytes;
|
1979 |
+
if (!getid3_lib::intValueSupported($pos)) {
|
1980 |
+
throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') because beyond PHP filesystem limit', 10);
|
|
|
|
|
|
|
1981 |
}
|
1982 |
|
1983 |
+
//return fread($this->getid3->fp, $bytes);
|
1984 |
+
/*
|
1985 |
+
* https://www.getid3.org/phpBB3/viewtopic.php?t=1930
|
1986 |
+
* "I found out that the root cause for the problem was how getID3 uses the PHP system function fread().
|
1987 |
+
* It seems to assume that fread() would always return as many bytes as were requested.
|
1988 |
+
* However, according the PHP manual (http://php.net/manual/en/function.fread.php), this is the case only with regular local files, but not e.g. with Linux pipes.
|
1989 |
+
* The call may return only part of the requested data and a new call is needed to get more."
|
1990 |
+
*/
|
1991 |
+
$contents = '';
|
1992 |
+
do {
|
1993 |
+
//if (($this->getid3->memory_limit > 0) && ($bytes > $this->getid3->memory_limit)) {
|
1994 |
+
if (($this->getid3->memory_limit > 0) && (($bytes / $this->getid3->memory_limit) > 0.99)) { // enable a more-fuzzy match to prevent close misses generating errors like "PHP Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 33554464 bytes)"
|
1995 |
+
throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') that is more than available PHP memory ('.$this->getid3->memory_limit.')', 10);
|
1996 |
}
|
1997 |
+
$part = fread($this->getid3->fp, $bytes);
|
1998 |
+
$partLength = strlen($part);
|
1999 |
+
$bytes -= $partLength;
|
2000 |
+
$contents .= $part;
|
2001 |
+
} while (($bytes > 0) && ($partLength > 0));
|
2002 |
+
return $contents;
|
2003 |
+
}
|
2004 |
|
2005 |
+
/**
|
2006 |
+
* @param int $bytes
|
2007 |
+
* @param int $whence
|
2008 |
+
*
|
2009 |
+
* @return int
|
2010 |
+
*
|
2011 |
+
* @throws getid3_exception
|
2012 |
+
*/
|
2013 |
+
protected function fseek($bytes, $whence=SEEK_SET) {
|
2014 |
+
if ($this->data_string_flag) {
|
2015 |
+
switch ($whence) {
|
2016 |
+
case SEEK_SET:
|
2017 |
+
$this->data_string_position = $bytes;
|
2018 |
+
break;
|
2019 |
|
2020 |
+
case SEEK_CUR:
|
2021 |
+
$this->data_string_position += $bytes;
|
2022 |
+
break;
|
2023 |
|
2024 |
+
case SEEK_END:
|
2025 |
+
$this->data_string_position = $this->data_string_length + $bytes;
|
2026 |
+
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2027 |
}
|
2028 |
+
return 0;
|
2029 |
+
} else {
|
2030 |
+
$pos = $bytes;
|
2031 |
+
if ($whence == SEEK_CUR) {
|
2032 |
+
$pos = $this->ftell() + $bytes;
|
2033 |
+
} elseif ($whence == SEEK_END) {
|
2034 |
+
$pos = $this->getid3->info['filesize'] + $bytes;
|
2035 |
+
}
|
2036 |
+
if (!getid3_lib::intValueSupported($pos)) {
|
2037 |
+
throw new getid3_exception('cannot fseek('.$pos.') because beyond PHP filesystem limit', 10);
|
2038 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2039 |
}
|
2040 |
+
return fseek($this->getid3->fp, $bytes, $whence);
|
2041 |
+
}
|
2042 |
|
2043 |
+
/**
|
2044 |
+
* @return bool
|
2045 |
+
*/
|
2046 |
+
protected function feof() {
|
2047 |
+
if ($this->data_string_flag) {
|
2048 |
+
return $this->data_string_position >= $this->data_string_length;
|
2049 |
}
|
2050 |
+
return feof($this->getid3->fp);
|
2051 |
+
}
|
2052 |
|
2053 |
+
/**
|
2054 |
+
* @param string $module
|
2055 |
+
*
|
2056 |
+
* @return bool
|
2057 |
+
*/
|
2058 |
+
final protected function isDependencyFor($module) {
|
2059 |
+
return $this->dependency_to == $module;
|
2060 |
+
}
|
2061 |
|
2062 |
+
/**
|
2063 |
+
* @param string $text
|
2064 |
+
*
|
2065 |
+
* @return bool
|
2066 |
+
*/
|
2067 |
+
protected function error($text) {
|
2068 |
+
$this->getid3->info['error'][] = $text;
|
2069 |
|
2070 |
+
return false;
|
2071 |
+
}
|
2072 |
|
2073 |
+
/**
|
2074 |
+
* @param string $text
|
2075 |
+
*
|
2076 |
+
* @return bool
|
2077 |
+
*/
|
2078 |
+
protected function warning($text) {
|
2079 |
+
return $this->getid3->warning($text);
|
2080 |
+
}
|
2081 |
|
2082 |
+
/**
|
2083 |
+
* @param string $text
|
2084 |
+
*/
|
2085 |
+
protected function notice($text) {
|
2086 |
+
// does nothing for now
|
2087 |
+
}
|
2088 |
|
2089 |
+
/**
|
2090 |
+
* @param string $name
|
2091 |
+
* @param int $offset
|
2092 |
+
* @param int $length
|
2093 |
+
* @param string $image_mime
|
2094 |
+
*
|
2095 |
+
* @return string|null
|
2096 |
+
*
|
2097 |
+
* @throws Exception
|
2098 |
+
* @throws getid3_exception
|
2099 |
+
*/
|
2100 |
+
public function saveAttachment($name, $offset, $length, $image_mime=null) {
|
2101 |
+
try {
|
2102 |
+
|
2103 |
+
// do not extract at all
|
2104 |
+
if ($this->getid3->option_save_attachments === getID3::ATTACHMENTS_NONE) {
|
2105 |
+
|
2106 |
+
$attachment = null; // do not set any
|
2107 |
+
|
2108 |
+
// extract to return array
|
2109 |
+
} elseif ($this->getid3->option_save_attachments === getID3::ATTACHMENTS_INLINE) {
|
2110 |
+
|
2111 |
+
$this->fseek($offset);
|
2112 |
+
$attachment = $this->fread($length); // get whole data in one pass, till it is anyway stored in memory
|
2113 |
+
if ($attachment === false || strlen($attachment) != $length) {
|
2114 |
+
throw new Exception('failed to read attachment data');
|
2115 |
+
}
|
2116 |
|
2117 |
+
// assume directory path is given
|
2118 |
+
} else {
|
2119 |
|
2120 |
+
// set up destination path
|
2121 |
+
$dir = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->getid3->option_save_attachments), DIRECTORY_SEPARATOR);
|
2122 |
+
if (!is_dir($dir) || !getID3::is_writable($dir)) { // check supplied directory
|
2123 |
+
throw new Exception('supplied path ('.$dir.') does not exist, or is not writable');
|
2124 |
+
}
|
2125 |
+
$dest = $dir.DIRECTORY_SEPARATOR.$name.($image_mime ? '.'.getid3_lib::ImageExtFromMime($image_mime) : '');
|
2126 |
|
2127 |
+
// create dest file
|
2128 |
+
if (($fp_dest = fopen($dest, 'wb')) == false) {
|
2129 |
+
throw new Exception('failed to create file '.$dest);
|
2130 |
+
}
|
2131 |
|
2132 |
+
// copy data
|
2133 |
+
$this->fseek($offset);
|
2134 |
+
$buffersize = ($this->data_string_flag ? $length : $this->getid3->fread_buffer_size());
|
2135 |
+
$bytesleft = $length;
|
2136 |
+
while ($bytesleft > 0) {
|
2137 |
+
if (($buffer = $this->fread(min($buffersize, $bytesleft))) === false || ($byteswritten = fwrite($fp_dest, $buffer)) === false || ($byteswritten === 0)) {
|
2138 |
+
throw new Exception($buffer === false ? 'not enough data to read' : 'failed to write to destination file, may be not enough disk space');
|
|
|
|
|
2139 |
}
|
2140 |
+
$bytesleft -= $byteswritten;
|
|
|
|
|
|
|
2141 |
}
|
2142 |
|
2143 |
+
fclose($fp_dest);
|
2144 |
+
$attachment = $dest;
|
2145 |
|
2146 |
+
}
|
|
|
|
|
|
|
|
|
2147 |
|
2148 |
+
} catch (Exception $e) {
|
|
|
|
|
2149 |
|
2150 |
+
// close and remove dest file if created
|
2151 |
+
if (isset($fp_dest) && is_resource($fp_dest)) {
|
2152 |
+
fclose($fp_dest);
|
2153 |
}
|
2154 |
|
2155 |
+
if (isset($dest) && file_exists($dest)) {
|
2156 |
+
unlink($dest);
|
2157 |
+
}
|
2158 |
+
|
2159 |
+
// do not set any is case of error
|
2160 |
+
$attachment = null;
|
2161 |
+
$this->warning('Failed to extract attachment '.$name.': '.$e->getMessage());
|
2162 |
|
|
|
2163 |
}
|
2164 |
|
2165 |
+
// seek to the end of attachment
|
2166 |
+
$this->fseek($offset + $length);
|
2167 |
+
|
2168 |
+
return $attachment;
|
2169 |
}
|
2170 |
+
|
2171 |
}
|
2172 |
|
2173 |
|
2174 |
+
class getid3_exception extends Exception
|
2175 |
+
{
|
2176 |
+
public $message;
|
|
|
|
|
2177 |
}
|
lib/getid3/module.archive.gzip.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.archive.gzip.php //
|
@@ -20,11 +20,20 @@
|
|
20 |
/////////////////////////////////////////////////////////////////
|
21 |
|
22 |
|
23 |
-
class getid3_gzip extends getid3_handler
|
24 |
-
|
25 |
-
|
26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
|
|
|
|
|
|
|
28 |
public function Analyze() {
|
29 |
$info = &$this->getid3->info;
|
30 |
|
@@ -37,13 +46,14 @@ class getid3_gzip extends getid3_handler {
|
|
37 |
//+---+---+---+---+---+---+---+---+---+---+
|
38 |
|
39 |
if ($info['php_memory_limit'] && ($info['filesize'] > $info['php_memory_limit'])) {
|
40 |
-
$
|
41 |
return false;
|
42 |
}
|
43 |
$this->fseek(0);
|
44 |
$buffer = $this->fread($info['filesize']);
|
45 |
|
46 |
$arr_members = explode("\x1F\x8B\x08", $buffer);
|
|
|
47 |
while (true) {
|
48 |
$is_wrong_members = false;
|
49 |
$num_members = intval(count($arr_members));
|
@@ -97,7 +107,7 @@ class getid3_gzip extends getid3_handler {
|
|
97 |
|
98 |
$thisInfo['os'] = $this->get_os_type($thisInfo['raw']['os']);
|
99 |
if (!$thisInfo['os']) {
|
100 |
-
$
|
101 |
return false;
|
102 |
}
|
103 |
|
@@ -199,7 +209,7 @@ class getid3_gzip extends getid3_handler {
|
|
199 |
$inflated = gzinflate($cdata);
|
200 |
|
201 |
// Calculate CRC32 for inflated content
|
202 |
-
$thisInfo['crc32_valid'] =
|
203 |
|
204 |
// determine format
|
205 |
$formattest = substr($inflated, 0, 32774);
|
@@ -215,7 +225,7 @@ class getid3_gzip extends getid3_handler {
|
|
215 |
if (file_exists(GETID3_INCLUDEPATH.$determined_format['include']) && include_once(GETID3_INCLUDEPATH.$determined_format['include'])) {
|
216 |
if (($temp_tar_filename = tempnam(GETID3_TEMP_DIR, 'getID3')) === false) {
|
217 |
// can't find anywhere to create a temp file, abort
|
218 |
-
$
|
219 |
break;
|
220 |
}
|
221 |
if ($fp_temp_tar = fopen($temp_tar_filename, 'w+b')) {
|
@@ -229,7 +239,7 @@ class getid3_gzip extends getid3_handler {
|
|
229 |
unset($getid3_temp, $getid3_tar);
|
230 |
unlink($temp_tar_filename);
|
231 |
} else {
|
232 |
-
$
|
233 |
break;
|
234 |
}
|
235 |
}
|
@@ -240,13 +250,21 @@ class getid3_gzip extends getid3_handler {
|
|
240 |
// unknown or unhandled format
|
241 |
break;
|
242 |
}
|
|
|
|
|
243 |
}
|
244 |
}
|
245 |
}
|
246 |
return true;
|
247 |
}
|
248 |
|
249 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
250 |
public function get_os_type($key) {
|
251 |
static $os_type = array(
|
252 |
'0' => 'FAT filesystem (MS-DOS, OS/2, NT/Win32)',
|
@@ -268,7 +286,13 @@ class getid3_gzip extends getid3_handler {
|
|
268 |
return (isset($os_type[$key]) ? $os_type[$key] : '');
|
269 |
}
|
270 |
|
271 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
272 |
public function get_xflag_type($key) {
|
273 |
static $xflag_type = array(
|
274 |
'0' => 'unknown',
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.archive.gzip.php //
|
20 |
/////////////////////////////////////////////////////////////////
|
21 |
|
22 |
|
23 |
+
class getid3_gzip extends getid3_handler
|
24 |
+
{
|
25 |
+
/**
|
26 |
+
* Optional file list - disable for speed.
|
27 |
+
*
|
28 |
+
* Decode gzipped files, if possible, and parse recursively (.tar.gz for example).
|
29 |
+
*
|
30 |
+
* @var bool
|
31 |
+
*/
|
32 |
+
public $option_gzip_parse_contents = false;
|
33 |
|
34 |
+
/**
|
35 |
+
* @return bool
|
36 |
+
*/
|
37 |
public function Analyze() {
|
38 |
$info = &$this->getid3->info;
|
39 |
|
46 |
//+---+---+---+---+---+---+---+---+---+---+
|
47 |
|
48 |
if ($info['php_memory_limit'] && ($info['filesize'] > $info['php_memory_limit'])) {
|
49 |
+
$this->error('File is too large ('.number_format($info['filesize']).' bytes) to read into memory (limit: '.number_format($info['php_memory_limit'] / 1048576).'MB)');
|
50 |
return false;
|
51 |
}
|
52 |
$this->fseek(0);
|
53 |
$buffer = $this->fread($info['filesize']);
|
54 |
|
55 |
$arr_members = explode("\x1F\x8B\x08", $buffer);
|
56 |
+
$num_members = 0;
|
57 |
while (true) {
|
58 |
$is_wrong_members = false;
|
59 |
$num_members = intval(count($arr_members));
|
107 |
|
108 |
$thisInfo['os'] = $this->get_os_type($thisInfo['raw']['os']);
|
109 |
if (!$thisInfo['os']) {
|
110 |
+
$this->error('Read error on gzip file');
|
111 |
return false;
|
112 |
}
|
113 |
|
209 |
$inflated = gzinflate($cdata);
|
210 |
|
211 |
// Calculate CRC32 for inflated content
|
212 |
+
$thisInfo['crc32_valid'] = sprintf('%u', crc32($inflated)) == $thisInfo['crc32'];
|
213 |
|
214 |
// determine format
|
215 |
$formattest = substr($inflated, 0, 32774);
|
225 |
if (file_exists(GETID3_INCLUDEPATH.$determined_format['include']) && include_once(GETID3_INCLUDEPATH.$determined_format['include'])) {
|
226 |
if (($temp_tar_filename = tempnam(GETID3_TEMP_DIR, 'getID3')) === false) {
|
227 |
// can't find anywhere to create a temp file, abort
|
228 |
+
$this->error('Unable to create temp file to parse TAR inside GZIP file');
|
229 |
break;
|
230 |
}
|
231 |
if ($fp_temp_tar = fopen($temp_tar_filename, 'w+b')) {
|
239 |
unset($getid3_temp, $getid3_tar);
|
240 |
unlink($temp_tar_filename);
|
241 |
} else {
|
242 |
+
$this->error('Unable to fopen() temp file to parse TAR inside GZIP file');
|
243 |
break;
|
244 |
}
|
245 |
}
|
250 |
// unknown or unhandled format
|
251 |
break;
|
252 |
}
|
253 |
+
} else {
|
254 |
+
$this->warning('PHP is not compiled with gzinflate() support. Please enable PHP Zlib extension or recompile with the --with-zlib switch');
|
255 |
}
|
256 |
}
|
257 |
}
|
258 |
return true;
|
259 |
}
|
260 |
|
261 |
+
/**
|
262 |
+
* Converts the OS type.
|
263 |
+
*
|
264 |
+
* @param string $key
|
265 |
+
*
|
266 |
+
* @return string
|
267 |
+
*/
|
268 |
public function get_os_type($key) {
|
269 |
static $os_type = array(
|
270 |
'0' => 'FAT filesystem (MS-DOS, OS/2, NT/Win32)',
|
286 |
return (isset($os_type[$key]) ? $os_type[$key] : '');
|
287 |
}
|
288 |
|
289 |
+
/**
|
290 |
+
* Converts the eXtra FLags.
|
291 |
+
*
|
292 |
+
* @param string $key
|
293 |
+
*
|
294 |
+
* @return string
|
295 |
+
*/
|
296 |
public function get_xflag_type($key) {
|
297 |
static $xflag_type = array(
|
298 |
'0' => 'unknown',
|
lib/getid3/module.archive.rar.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.archive.rar.php //
|
@@ -17,9 +17,14 @@
|
|
17 |
|
18 |
class getid3_rar extends getid3_handler
|
19 |
{
|
20 |
-
|
|
|
|
|
21 |
public $option_use_rar_extension = false;
|
22 |
|
|
|
|
|
|
|
23 |
public function Analyze() {
|
24 |
$info = &$this->getid3->info;
|
25 |
|
@@ -36,13 +41,13 @@ class getid3_rar extends getid3_handler
|
|
36 |
rar_close($rp);
|
37 |
return true;
|
38 |
} else {
|
39 |
-
$
|
40 |
}
|
41 |
} else {
|
42 |
-
$
|
43 |
}
|
44 |
} else {
|
45 |
-
$
|
46 |
}
|
47 |
return false;
|
48 |
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.archive.rar.php //
|
17 |
|
18 |
class getid3_rar extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @var bool
|
22 |
+
*/
|
23 |
public $option_use_rar_extension = false;
|
24 |
|
25 |
+
/**
|
26 |
+
* @return bool
|
27 |
+
*/
|
28 |
public function Analyze() {
|
29 |
$info = &$this->getid3->info;
|
30 |
|
41 |
rar_close($rp);
|
42 |
return true;
|
43 |
} else {
|
44 |
+
$this->error('failed to rar_open('.$info['filename'].')');
|
45 |
}
|
46 |
} else {
|
47 |
+
$this->error('RAR support does not appear to be available in this PHP installation');
|
48 |
}
|
49 |
} else {
|
50 |
+
$this->error('PHP-RAR processing has been disabled (set $getid3_rar->option_use_rar_extension=true to enable)');
|
51 |
}
|
52 |
return false;
|
53 |
|
lib/getid3/module.archive.szip.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.archive.szip.php //
|
@@ -17,21 +17,23 @@
|
|
17 |
|
18 |
class getid3_szip extends getid3_handler
|
19 |
{
|
20 |
-
|
|
|
|
|
21 |
public function Analyze() {
|
22 |
$info = &$this->getid3->info;
|
23 |
|
24 |
$this->fseek($info['avdataoffset']);
|
25 |
$SZIPHeader = $this->fread(6);
|
26 |
if (substr($SZIPHeader, 0, 4) != "SZ\x0A\x04") {
|
27 |
-
$
|
28 |
return false;
|
29 |
}
|
30 |
$info['fileformat'] = 'szip';
|
31 |
$info['szip']['major_version'] = getid3_lib::BigEndian2Int(substr($SZIPHeader, 4, 1));
|
32 |
$info['szip']['minor_version'] = getid3_lib::BigEndian2Int(substr($SZIPHeader, 5, 1));
|
33 |
-
$
|
34 |
-
return false;
|
35 |
|
36 |
while (!$this->feof()) {
|
37 |
$NextBlockID = $this->fread(2);
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.archive.szip.php //
|
17 |
|
18 |
class getid3_szip extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @return bool
|
22 |
+
*/
|
23 |
public function Analyze() {
|
24 |
$info = &$this->getid3->info;
|
25 |
|
26 |
$this->fseek($info['avdataoffset']);
|
27 |
$SZIPHeader = $this->fread(6);
|
28 |
if (substr($SZIPHeader, 0, 4) != "SZ\x0A\x04") {
|
29 |
+
$this->error('Expecting "53 5A 0A 04" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($SZIPHeader, 0, 4)).'"');
|
30 |
return false;
|
31 |
}
|
32 |
$info['fileformat'] = 'szip';
|
33 |
$info['szip']['major_version'] = getid3_lib::BigEndian2Int(substr($SZIPHeader, 4, 1));
|
34 |
$info['szip']['minor_version'] = getid3_lib::BigEndian2Int(substr($SZIPHeader, 5, 1));
|
35 |
+
$this->error('SZIP parsing not enabled in this version of getID3() ['.$this->getid3->version().']');
|
36 |
+
return false;
|
37 |
|
38 |
while (!$this->feof()) {
|
39 |
$NextBlockID = $this->fread(2);
|
lib/getid3/module.archive.tar.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.archive.tar.php //
|
@@ -22,7 +22,9 @@
|
|
22 |
|
23 |
class getid3_tar extends getid3_handler
|
24 |
{
|
25 |
-
|
|
|
|
|
26 |
public function Analyze() {
|
27 |
$info = &$this->getid3->info;
|
28 |
|
@@ -117,7 +119,13 @@ class getid3_tar extends getid3_handler
|
|
117 |
return true;
|
118 |
}
|
119 |
|
120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
public function display_perms($mode) {
|
122 |
// Determine Type
|
123 |
if ($mode & 0x1000) $type='p'; // FIFO pipe
|
@@ -152,7 +160,13 @@ class getid3_tar extends getid3_handler
|
|
152 |
return $s;
|
153 |
}
|
154 |
|
155 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
public function get_flag_type($typflag) {
|
157 |
static $flag_types = array(
|
158 |
'0' => 'LF_NORMAL',
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.archive.tar.php //
|
22 |
|
23 |
class getid3_tar extends getid3_handler
|
24 |
{
|
25 |
+
/**
|
26 |
+
* @return bool
|
27 |
+
*/
|
28 |
public function Analyze() {
|
29 |
$info = &$this->getid3->info;
|
30 |
|
119 |
return true;
|
120 |
}
|
121 |
|
122 |
+
/**
|
123 |
+
* Parses the file mode to file permissions.
|
124 |
+
*
|
125 |
+
* @param int $mode
|
126 |
+
*
|
127 |
+
* @return string
|
128 |
+
*/
|
129 |
public function display_perms($mode) {
|
130 |
// Determine Type
|
131 |
if ($mode & 0x1000) $type='p'; // FIFO pipe
|
160 |
return $s;
|
161 |
}
|
162 |
|
163 |
+
/**
|
164 |
+
* Converts the file type.
|
165 |
+
*
|
166 |
+
* @param string $typflag
|
167 |
+
*
|
168 |
+
* @return mixed|string
|
169 |
+
*/
|
170 |
public function get_flag_type($typflag) {
|
171 |
static $flag_types = array(
|
172 |
'0' => 'LF_NORMAL',
|
lib/getid3/module.archive.xz.php
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/////////////////////////////////////////////////////////////////
|
4 |
+
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
9 |
+
/////////////////////////////////////////////////////////////////
|
10 |
+
// //
|
11 |
+
// module.archive.xz.php //
|
12 |
+
// module for analyzing XZ files //
|
13 |
+
// dependencies: NONE //
|
14 |
+
// ///
|
15 |
+
/////////////////////////////////////////////////////////////////
|
16 |
+
|
17 |
+
|
18 |
+
class getid3_xz extends getid3_handler
|
19 |
+
{
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @return bool
|
23 |
+
*/
|
24 |
+
public function Analyze() {
|
25 |
+
$info = &$this->getid3->info;
|
26 |
+
|
27 |
+
$this->fseek($info['avdataoffset']);
|
28 |
+
$xzheader = $this->fread(6);
|
29 |
+
|
30 |
+
// https://tukaani.org/xz/xz-file-format-1.0.4.txt
|
31 |
+
$info['xz']['stream_header']['magic'] = substr($xzheader, 0, 6);
|
32 |
+
if ($info['xz']['stream_header']['magic'] != "\xFD".'7zXZ'."\x00") {
|
33 |
+
$this->error('Invalid XZ stream header magic (expecting FD 37 7A 58 5A 00, found '.getid3_lib::PrintHexBytes($info['xz']['stream_header']['magic']).') at offset '.$info['avdataoffset']);
|
34 |
+
return false;
|
35 |
+
}
|
36 |
+
$info['fileformat'] = 'xz';
|
37 |
+
$this->error('XZ parsing not enabled in this version of getID3() ['.$this->getid3->version().']');
|
38 |
+
return false;
|
39 |
+
|
40 |
+
}
|
41 |
+
|
42 |
+
}
|
lib/getid3/module.archive.zip.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.archive.zip.php //
|
@@ -17,7 +17,9 @@
|
|
17 |
|
18 |
class getid3_zip extends getid3_handler
|
19 |
{
|
20 |
-
|
|
|
|
|
21 |
public function Analyze() {
|
22 |
$info = &$this->getid3->info;
|
23 |
|
@@ -30,7 +32,7 @@ class getid3_zip extends getid3_handler
|
|
30 |
$info['zip']['entries_count'] = 0;
|
31 |
|
32 |
if (!getid3_lib::intValueSupported($info['filesize'])) {
|
33 |
-
$
|
34 |
return false;
|
35 |
} else {
|
36 |
$EOCDsearchData = '';
|
@@ -48,7 +50,7 @@ class getid3_zip extends getid3_handler
|
|
48 |
|
49 |
$this->fseek($info['zip']['end_central_directory']['directory_offset']);
|
50 |
$info['zip']['entries_count'] = 0;
|
51 |
-
while ($centraldirectoryentry = $this->ZIPparseCentralDirectory(
|
52 |
$info['zip']['central_directory'][] = $centraldirectoryentry;
|
53 |
$info['zip']['entries_count']++;
|
54 |
$info['zip']['compressed_size'] += $centraldirectoryentry['compressed_size'];
|
@@ -61,7 +63,7 @@ class getid3_zip extends getid3_handler
|
|
61 |
}
|
62 |
|
63 |
if ($info['zip']['entries_count'] == 0) {
|
64 |
-
$
|
65 |
return false;
|
66 |
}
|
67 |
|
@@ -86,7 +88,7 @@ class getid3_zip extends getid3_handler
|
|
86 |
if ($fileentry = $this->ZIPparseLocalFileHeader()) {
|
87 |
$info['zip']['entries'][] = $fileentry;
|
88 |
} else {
|
89 |
-
$
|
90 |
}
|
91 |
}
|
92 |
|
@@ -94,15 +96,15 @@ class getid3_zip extends getid3_handler
|
|
94 |
!empty($info['zip']['files']['_rels']['.rels']) &&
|
95 |
!empty($info['zip']['files']['docProps']['app.xml']) &&
|
96 |
!empty($info['zip']['files']['docProps']['core.xml'])) {
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
}
|
107 |
|
108 |
return true;
|
@@ -113,23 +115,25 @@ class getid3_zip extends getid3_handler
|
|
113 |
if (!$this->getZIPentriesFilepointer()) {
|
114 |
unset($info['zip']);
|
115 |
$info['fileformat'] = '';
|
116 |
-
$
|
117 |
return false;
|
118 |
}
|
119 |
|
120 |
// central directory couldn't be found and/or parsed
|
121 |
// scan through actual file data entries, recover as much as possible from probable trucated file
|
122 |
if ($info['zip']['compressed_size'] > ($info['filesize'] - 46 - 22)) {
|
123 |
-
$
|
124 |
}
|
125 |
-
$
|
126 |
foreach ($info['zip']['entries'] as $key => $valuearray) {
|
127 |
$info['zip']['files'][$valuearray['filename']] = $valuearray['uncompressed_size'];
|
128 |
}
|
129 |
return true;
|
130 |
}
|
131 |
|
132 |
-
|
|
|
|
|
133 |
public function getZIPHeaderFilepointerTopDown() {
|
134 |
$info = &$this->getid3->info;
|
135 |
|
@@ -145,26 +149,26 @@ class getid3_zip extends getid3_handler
|
|
145 |
$info['zip']['entries_count']++;
|
146 |
}
|
147 |
if ($info['zip']['entries_count'] == 0) {
|
148 |
-
$
|
149 |
return false;
|
150 |
}
|
151 |
|
152 |
$info['zip']['entries_count'] = 0;
|
153 |
-
while ($centraldirectoryentry = $this->ZIPparseCentralDirectory(
|
154 |
$info['zip']['central_directory'][] = $centraldirectoryentry;
|
155 |
$info['zip']['entries_count']++;
|
156 |
$info['zip']['compressed_size'] += $centraldirectoryentry['compressed_size'];
|
157 |
$info['zip']['uncompressed_size'] += $centraldirectoryentry['uncompressed_size'];
|
158 |
}
|
159 |
if ($info['zip']['entries_count'] == 0) {
|
160 |
-
$
|
161 |
return false;
|
162 |
}
|
163 |
|
164 |
if ($EOCD = $this->ZIPparseEndOfCentralDirectory()) {
|
165 |
$info['zip']['end_central_directory'] = $EOCD;
|
166 |
} else {
|
167 |
-
$
|
168 |
return false;
|
169 |
}
|
170 |
|
@@ -175,7 +179,9 @@ class getid3_zip extends getid3_handler
|
|
175 |
return true;
|
176 |
}
|
177 |
|
178 |
-
|
|
|
|
|
179 |
public function getZIPentriesFilepointer() {
|
180 |
$info = &$this->getid3->info;
|
181 |
|
@@ -191,14 +197,16 @@ class getid3_zip extends getid3_handler
|
|
191 |
$info['zip']['uncompressed_size'] += $fileentry['uncompressed_size'];
|
192 |
}
|
193 |
if ($info['zip']['entries_count'] == 0) {
|
194 |
-
$
|
195 |
return false;
|
196 |
}
|
197 |
|
198 |
return true;
|
199 |
}
|
200 |
|
201 |
-
|
|
|
|
|
202 |
public function ZIPparseLocalFileHeader() {
|
203 |
$LocalFileHeader['offset'] = $this->ftell();
|
204 |
|
@@ -265,7 +273,7 @@ class getid3_zip extends getid3_handler
|
|
265 |
$DataDescriptor = $this->fread(16);
|
266 |
$LocalFileHeader['data_descriptor']['signature'] = getid3_lib::LittleEndian2Int(substr($DataDescriptor, 0, 4));
|
267 |
if ($LocalFileHeader['data_descriptor']['signature'] != 0x08074B50) { // "PK\x07\x08"
|
268 |
-
$this->getid3->warning
|
269 |
$this->fseek($LocalFileHeader['offset']); // seek back to where filepointer originally was so it can be handled properly
|
270 |
return false;
|
271 |
}
|
@@ -278,13 +286,13 @@ class getid3_zip extends getid3_handler
|
|
278 |
if ($LocalFileHeader['data_descriptor']['compressed_size'] == $central_directory_entry['compressed_size']) {
|
279 |
// $LocalFileHeader['compressed_size'] already set from Central Directory
|
280 |
} else {
|
281 |
-
$this->
|
282 |
}
|
283 |
|
284 |
if ($LocalFileHeader['data_descriptor']['uncompressed_size'] == $central_directory_entry['uncompressed_size']) {
|
285 |
$LocalFileHeader['uncompressed_size'] = $LocalFileHeader['data_descriptor']['uncompressed_size'];
|
286 |
} else {
|
287 |
-
$this->
|
288 |
}
|
289 |
break;
|
290 |
}
|
@@ -294,7 +302,9 @@ class getid3_zip extends getid3_handler
|
|
294 |
return $LocalFileHeader;
|
295 |
}
|
296 |
|
297 |
-
|
|
|
|
|
298 |
public function ZIPparseCentralDirectory() {
|
299 |
$CentralDirectory['offset'] = $this->ftell();
|
300 |
|
@@ -351,6 +361,9 @@ class getid3_zip extends getid3_handler
|
|
351 |
return $CentralDirectory;
|
352 |
}
|
353 |
|
|
|
|
|
|
|
354 |
public function ZIPparseEndOfCentralDirectory() {
|
355 |
$EndOfCentralDirectory['offset'] = $this->ftell();
|
356 |
|
@@ -377,9 +390,15 @@ class getid3_zip extends getid3_handler
|
|
377 |
return $EndOfCentralDirectory;
|
378 |
}
|
379 |
|
380 |
-
|
|
|
|
|
|
|
|
|
|
|
381 |
public static function ZIPparseGeneralPurposeFlags($flagbytes, $compressionmethod) {
|
382 |
// https://users.cs.jmu.edu/buchhofp/forensics/formats/pkzip-printable.html
|
|
|
383 |
$ParsedFlags['encrypted'] = (bool) ($flagbytes & 0x0001);
|
384 |
// 0x0002 -- see below
|
385 |
// 0x0004 -- see below
|
@@ -425,7 +444,11 @@ class getid3_zip extends getid3_handler
|
|
425 |
return $ParsedFlags;
|
426 |
}
|
427 |
|
428 |
-
|
|
|
|
|
|
|
|
|
429 |
public static function ZIPversionOSLookup($index) {
|
430 |
static $ZIPversionOSLookup = array(
|
431 |
0 => 'MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems)',
|
@@ -453,6 +476,11 @@ class getid3_zip extends getid3_handler
|
|
453 |
return (isset($ZIPversionOSLookup[$index]) ? $ZIPversionOSLookup[$index] : '[unknown]');
|
454 |
}
|
455 |
|
|
|
|
|
|
|
|
|
|
|
456 |
public static function ZIPcompressionMethodLookup($index) {
|
457 |
// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/ZIP.html
|
458 |
static $ZIPcompressionMethodLookup = array(
|
@@ -484,6 +512,12 @@ class getid3_zip extends getid3_handler
|
|
484 |
return (isset($ZIPcompressionMethodLookup[$index]) ? $ZIPcompressionMethodLookup[$index] : '[unknown]');
|
485 |
}
|
486 |
|
|
|
|
|
|
|
|
|
|
|
|
|
487 |
public static function DOStime2UNIXtime($DOSdate, $DOStime) {
|
488 |
// wFatDate
|
489 |
// Specifies the MS-DOS date. The date is a packed 16-bit value with the following format:
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.archive.zip.php //
|
17 |
|
18 |
class getid3_zip extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @return bool
|
22 |
+
*/
|
23 |
public function Analyze() {
|
24 |
$info = &$this->getid3->info;
|
25 |
|
32 |
$info['zip']['entries_count'] = 0;
|
33 |
|
34 |
if (!getid3_lib::intValueSupported($info['filesize'])) {
|
35 |
+
$this->error('File is larger than '.round(PHP_INT_MAX / 1073741824).'GB, not supported by PHP');
|
36 |
return false;
|
37 |
} else {
|
38 |
$EOCDsearchData = '';
|
50 |
|
51 |
$this->fseek($info['zip']['end_central_directory']['directory_offset']);
|
52 |
$info['zip']['entries_count'] = 0;
|
53 |
+
while ($centraldirectoryentry = $this->ZIPparseCentralDirectory()) {
|
54 |
$info['zip']['central_directory'][] = $centraldirectoryentry;
|
55 |
$info['zip']['entries_count']++;
|
56 |
$info['zip']['compressed_size'] += $centraldirectoryentry['compressed_size'];
|
63 |
}
|
64 |
|
65 |
if ($info['zip']['entries_count'] == 0) {
|
66 |
+
$this->error('No Central Directory entries found (truncated file?)');
|
67 |
return false;
|
68 |
}
|
69 |
|
88 |
if ($fileentry = $this->ZIPparseLocalFileHeader()) {
|
89 |
$info['zip']['entries'][] = $fileentry;
|
90 |
} else {
|
91 |
+
$this->warning('Error parsing Local File Header at offset '.$central_directory_entry['entry_offset']);
|
92 |
}
|
93 |
}
|
94 |
|
96 |
!empty($info['zip']['files']['_rels']['.rels']) &&
|
97 |
!empty($info['zip']['files']['docProps']['app.xml']) &&
|
98 |
!empty($info['zip']['files']['docProps']['core.xml'])) {
|
99 |
+
// http://technet.microsoft.com/en-us/library/cc179224.aspx
|
100 |
+
$info['fileformat'] = 'zip.msoffice';
|
101 |
+
if (!empty($ThisFileInfo['zip']['files']['ppt'])) {
|
102 |
+
$info['mime_type'] = 'application/vnd.openxmlformats-officedocument.presentationml.presentation';
|
103 |
+
} elseif (!empty($ThisFileInfo['zip']['files']['xl'])) {
|
104 |
+
$info['mime_type'] = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
|
105 |
+
} elseif (!empty($ThisFileInfo['zip']['files']['word'])) {
|
106 |
+
$info['mime_type'] = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
|
107 |
+
}
|
108 |
}
|
109 |
|
110 |
return true;
|
115 |
if (!$this->getZIPentriesFilepointer()) {
|
116 |
unset($info['zip']);
|
117 |
$info['fileformat'] = '';
|
118 |
+
$this->error('Cannot find End Of Central Directory (truncated file?)');
|
119 |
return false;
|
120 |
}
|
121 |
|
122 |
// central directory couldn't be found and/or parsed
|
123 |
// scan through actual file data entries, recover as much as possible from probable trucated file
|
124 |
if ($info['zip']['compressed_size'] > ($info['filesize'] - 46 - 22)) {
|
125 |
+
$this->error('Warning: Truncated file! - Total compressed file sizes ('.$info['zip']['compressed_size'].' bytes) is greater than filesize minus Central Directory and End Of Central Directory structures ('.($info['filesize'] - 46 - 22).' bytes)');
|
126 |
}
|
127 |
+
$this->error('Cannot find End Of Central Directory - returned list of files in [zip][entries] array may not be complete');
|
128 |
foreach ($info['zip']['entries'] as $key => $valuearray) {
|
129 |
$info['zip']['files'][$valuearray['filename']] = $valuearray['uncompressed_size'];
|
130 |
}
|
131 |
return true;
|
132 |
}
|
133 |
|
134 |
+
/**
|
135 |
+
* @return bool
|
136 |
+
*/
|
137 |
public function getZIPHeaderFilepointerTopDown() {
|
138 |
$info = &$this->getid3->info;
|
139 |
|
149 |
$info['zip']['entries_count']++;
|
150 |
}
|
151 |
if ($info['zip']['entries_count'] == 0) {
|
152 |
+
$this->error('No Local File Header entries found');
|
153 |
return false;
|
154 |
}
|
155 |
|
156 |
$info['zip']['entries_count'] = 0;
|
157 |
+
while ($centraldirectoryentry = $this->ZIPparseCentralDirectory()) {
|
158 |
$info['zip']['central_directory'][] = $centraldirectoryentry;
|
159 |
$info['zip']['entries_count']++;
|
160 |
$info['zip']['compressed_size'] += $centraldirectoryentry['compressed_size'];
|
161 |
$info['zip']['uncompressed_size'] += $centraldirectoryentry['uncompressed_size'];
|
162 |
}
|
163 |
if ($info['zip']['entries_count'] == 0) {
|
164 |
+
$this->error('No Central Directory entries found (truncated file?)');
|
165 |
return false;
|
166 |
}
|
167 |
|
168 |
if ($EOCD = $this->ZIPparseEndOfCentralDirectory()) {
|
169 |
$info['zip']['end_central_directory'] = $EOCD;
|
170 |
} else {
|
171 |
+
$this->error('No End Of Central Directory entry found (truncated file?)');
|
172 |
return false;
|
173 |
}
|
174 |
|
179 |
return true;
|
180 |
}
|
181 |
|
182 |
+
/**
|
183 |
+
* @return bool
|
184 |
+
*/
|
185 |
public function getZIPentriesFilepointer() {
|
186 |
$info = &$this->getid3->info;
|
187 |
|
197 |
$info['zip']['uncompressed_size'] += $fileentry['uncompressed_size'];
|
198 |
}
|
199 |
if ($info['zip']['entries_count'] == 0) {
|
200 |
+
$this->error('No Local File Header entries found');
|
201 |
return false;
|
202 |
}
|
203 |
|
204 |
return true;
|
205 |
}
|
206 |
|
207 |
+
/**
|
208 |
+
* @return array|false
|
209 |
+
*/
|
210 |
public function ZIPparseLocalFileHeader() {
|
211 |
$LocalFileHeader['offset'] = $this->ftell();
|
212 |
|
273 |
$DataDescriptor = $this->fread(16);
|
274 |
$LocalFileHeader['data_descriptor']['signature'] = getid3_lib::LittleEndian2Int(substr($DataDescriptor, 0, 4));
|
275 |
if ($LocalFileHeader['data_descriptor']['signature'] != 0x08074B50) { // "PK\x07\x08"
|
276 |
+
$this->getid3->warning('invalid Local File Header Data Descriptor Signature at offset '.($this->ftell() - 16).' - expecting 08 07 4B 50, found '.getid3_lib::PrintHexBytes($LocalFileHeader['data_descriptor']['signature']));
|
277 |
$this->fseek($LocalFileHeader['offset']); // seek back to where filepointer originally was so it can be handled properly
|
278 |
return false;
|
279 |
}
|
286 |
if ($LocalFileHeader['data_descriptor']['compressed_size'] == $central_directory_entry['compressed_size']) {
|
287 |
// $LocalFileHeader['compressed_size'] already set from Central Directory
|
288 |
} else {
|
289 |
+
$this->warning('conflicting compressed_size from data_descriptor ('.$LocalFileHeader['data_descriptor']['compressed_size'].') vs Central Directory ('.$central_directory_entry['compressed_size'].') for file at offset '.$LocalFileHeader['offset']);
|
290 |
}
|
291 |
|
292 |
if ($LocalFileHeader['data_descriptor']['uncompressed_size'] == $central_directory_entry['uncompressed_size']) {
|
293 |
$LocalFileHeader['uncompressed_size'] = $LocalFileHeader['data_descriptor']['uncompressed_size'];
|
294 |
} else {
|
295 |
+
$this->warning('conflicting uncompressed_size from data_descriptor ('.$LocalFileHeader['data_descriptor']['uncompressed_size'].') vs Central Directory ('.$central_directory_entry['uncompressed_size'].') for file at offset '.$LocalFileHeader['offset']);
|
296 |
}
|
297 |
break;
|
298 |
}
|
302 |
return $LocalFileHeader;
|
303 |
}
|
304 |
|
305 |
+
/**
|
306 |
+
* @return array|false
|
307 |
+
*/
|
308 |
public function ZIPparseCentralDirectory() {
|
309 |
$CentralDirectory['offset'] = $this->ftell();
|
310 |
|
361 |
return $CentralDirectory;
|
362 |
}
|
363 |
|
364 |
+
/**
|
365 |
+
* @return array|false
|
366 |
+
*/
|
367 |
public function ZIPparseEndOfCentralDirectory() {
|
368 |
$EndOfCentralDirectory['offset'] = $this->ftell();
|
369 |
|
390 |
return $EndOfCentralDirectory;
|
391 |
}
|
392 |
|
393 |
+
/**
|
394 |
+
* @param int $flagbytes
|
395 |
+
* @param int $compressionmethod
|
396 |
+
*
|
397 |
+
* @return array
|
398 |
+
*/
|
399 |
public static function ZIPparseGeneralPurposeFlags($flagbytes, $compressionmethod) {
|
400 |
// https://users.cs.jmu.edu/buchhofp/forensics/formats/pkzip-printable.html
|
401 |
+
$ParsedFlags = array();
|
402 |
$ParsedFlags['encrypted'] = (bool) ($flagbytes & 0x0001);
|
403 |
// 0x0002 -- see below
|
404 |
// 0x0004 -- see below
|
444 |
return $ParsedFlags;
|
445 |
}
|
446 |
|
447 |
+
/**
|
448 |
+
* @param int $index
|
449 |
+
*
|
450 |
+
* @return string
|
451 |
+
*/
|
452 |
public static function ZIPversionOSLookup($index) {
|
453 |
static $ZIPversionOSLookup = array(
|
454 |
0 => 'MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems)',
|
476 |
return (isset($ZIPversionOSLookup[$index]) ? $ZIPversionOSLookup[$index] : '[unknown]');
|
477 |
}
|
478 |
|
479 |
+
/**
|
480 |
+
* @param int $index
|
481 |
+
*
|
482 |
+
* @return string
|
483 |
+
*/
|
484 |
public static function ZIPcompressionMethodLookup($index) {
|
485 |
// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/ZIP.html
|
486 |
static $ZIPcompressionMethodLookup = array(
|
512 |
return (isset($ZIPcompressionMethodLookup[$index]) ? $ZIPcompressionMethodLookup[$index] : '[unknown]');
|
513 |
}
|
514 |
|
515 |
+
/**
|
516 |
+
* @param int $DOSdate
|
517 |
+
* @param int $DOStime
|
518 |
+
*
|
519 |
+
* @return int
|
520 |
+
*/
|
521 |
public static function DOStime2UNIXtime($DOSdate, $DOStime) {
|
522 |
// wFatDate
|
523 |
// Specifies the MS-DOS date. The date is a packed 16-bit value with the following format:
|
lib/getid3/module.audio-video.asf.php
CHANGED
@@ -1,11 +1,10 @@
|
|
1 |
<?php
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio-video.asf.php //
|
@@ -16,8 +15,11 @@
|
|
16 |
|
17 |
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
|
18 |
|
19 |
-
class getid3_asf extends getid3_handler
|
20 |
-
|
|
|
|
|
|
|
21 |
public function __construct(getID3 $getid3) {
|
22 |
parent::__construct($getid3); // extends getid3_handler::__construct()
|
23 |
|
@@ -30,6 +32,9 @@ class getid3_asf extends getid3_handler {
|
|
30 |
}
|
31 |
}
|
32 |
|
|
|
|
|
|
|
33 |
public function Analyze() {
|
34 |
$info = &$this->getid3->info;
|
35 |
|
@@ -83,6 +88,8 @@ class getid3_asf extends getid3_handler {
|
|
83 |
$NextObjectOffset = $this->ftell();
|
84 |
$ASFHeaderData = $this->fread($thisfile_asf_headerobject['objectsize'] - 30);
|
85 |
$offset = 0;
|
|
|
|
|
86 |
|
87 |
for ($HeaderObjectsCounter = 0; $HeaderObjectsCounter < $thisfile_asf_headerobject['headerobjects']; $HeaderObjectsCounter++) {
|
88 |
$NextObjectGUID = substr($ASFHeaderData, $offset, 16);
|
@@ -266,14 +273,14 @@ class getid3_asf extends getid3_handler {
|
|
266 |
$offset += 16;
|
267 |
$thisfile_asf_headerextensionobject['reserved_1_guid'] = $this->BytestringToGUID($thisfile_asf_headerextensionobject['reserved_1']);
|
268 |
if ($thisfile_asf_headerextensionobject['reserved_1'] != GETID3_ASF_Reserved_1) {
|
269 |
-
$
|
270 |
//return false;
|
271 |
break;
|
272 |
}
|
273 |
$thisfile_asf_headerextensionobject['reserved_2'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
|
274 |
$offset += 2;
|
275 |
if ($thisfile_asf_headerextensionobject['reserved_2'] != 6) {
|
276 |
-
$
|
277 |
//return false;
|
278 |
break;
|
279 |
}
|
@@ -316,7 +323,7 @@ class getid3_asf extends getid3_handler {
|
|
316 |
$offset += 16;
|
317 |
$thisfile_asf_codeclistobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_codeclistobject['reserved']);
|
318 |
if ($thisfile_asf_codeclistobject['reserved'] != $this->GUIDtoBytestring('86D15241-311D-11D0-A3A4-00A0C90348F6')) {
|
319 |
-
$
|
320 |
//return false;
|
321 |
break;
|
322 |
}
|
@@ -349,7 +356,7 @@ class getid3_asf extends getid3_handler {
|
|
349 |
if ($thisfile_asf_codeclistobject_codecentries_current['type_raw'] == 2) { // audio codec
|
350 |
|
351 |
if (strpos($thisfile_asf_codeclistobject_codecentries_current['description'], ',') === false) {
|
352 |
-
$
|
353 |
} else {
|
354 |
|
355 |
list($AudioCodecBitrate, $AudioCodecFrequency, $AudioCodecChannels) = explode(',', $this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description']));
|
@@ -412,7 +419,7 @@ class getid3_asf extends getid3_handler {
|
|
412 |
break;
|
413 |
|
414 |
default:
|
415 |
-
$
|
416 |
break;
|
417 |
}
|
418 |
|
@@ -458,7 +465,7 @@ class getid3_asf extends getid3_handler {
|
|
458 |
$offset += 16;
|
459 |
$thisfile_asf_scriptcommandobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_scriptcommandobject['reserved']);
|
460 |
if ($thisfile_asf_scriptcommandobject['reserved'] != $this->GUIDtoBytestring('4B1ACBE3-100B-11D0-A39B-00A0C90348F6')) {
|
461 |
-
$
|
462 |
//return false;
|
463 |
break;
|
464 |
}
|
@@ -517,7 +524,7 @@ class getid3_asf extends getid3_handler {
|
|
517 |
$offset += 16;
|
518 |
$thisfile_asf_markerobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_markerobject['reserved']);
|
519 |
if ($thisfile_asf_markerobject['reserved'] != $this->GUIDtoBytestring('4CFEDB20-75F6-11CF-9C0F-00A0C90349CB')) {
|
520 |
-
$
|
521 |
break;
|
522 |
}
|
523 |
$thisfile_asf_markerobject['markers_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
|
@@ -525,7 +532,7 @@ class getid3_asf extends getid3_handler {
|
|
525 |
$thisfile_asf_markerobject['reserved_2'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
|
526 |
$offset += 2;
|
527 |
if ($thisfile_asf_markerobject['reserved_2'] != 0) {
|
528 |
-
$
|
529 |
break;
|
530 |
}
|
531 |
$thisfile_asf_markerobject['name_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
|
@@ -576,7 +583,7 @@ class getid3_asf extends getid3_handler {
|
|
576 |
$thisfile_asf_bitratemutualexclusionobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_bitratemutualexclusionobject['reserved']);
|
577 |
$offset += 16;
|
578 |
if (($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Bitrate) && ($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Unknown)) {
|
579 |
-
$
|
580 |
//return false;
|
581 |
break;
|
582 |
}
|
@@ -637,7 +644,7 @@ class getid3_asf extends getid3_handler {
|
|
637 |
break;
|
638 |
|
639 |
default:
|
640 |
-
$
|
641 |
//return false;
|
642 |
break;
|
643 |
}
|
@@ -761,7 +768,7 @@ class getid3_asf extends getid3_handler {
|
|
761 |
break;
|
762 |
|
763 |
default:
|
764 |
-
$
|
765 |
//return false;
|
766 |
break;
|
767 |
}
|
@@ -962,26 +969,26 @@ class getid3_asf extends getid3_handler {
|
|
962 |
default:
|
963 |
// Implementations shall ignore any standard or non-standard object that they do not know how to handle.
|
964 |
if ($this->GUIDname($NextObjectGUIDtext)) {
|
965 |
-
$
|
966 |
} else {
|
967 |
-
$
|
968 |
}
|
969 |
$offset += ($NextObjectSize - 16 - 8);
|
970 |
break;
|
971 |
}
|
972 |
}
|
973 |
-
if (isset($
|
974 |
$ASFbitrateAudio = 0;
|
975 |
$ASFbitrateVideo = 0;
|
976 |
-
for ($BitrateRecordsCounter = 0; $BitrateRecordsCounter < $
|
977 |
if (isset($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter])) {
|
978 |
switch ($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter]['type_raw']) {
|
979 |
case 1:
|
980 |
-
$ASFbitrateVideo += $
|
981 |
break;
|
982 |
|
983 |
case 2:
|
984 |
-
$ASFbitrateAudio += $
|
985 |
break;
|
986 |
|
987 |
default:
|
@@ -1183,7 +1190,7 @@ class getid3_asf extends getid3_handler {
|
|
1183 |
$thisfile_asf_dataobject['reserved'] = getid3_lib::LittleEndian2Int(substr($DataObjectData, $offset, 2));
|
1184 |
$offset += 2;
|
1185 |
if ($thisfile_asf_dataobject['reserved'] != 0x0101) {
|
1186 |
-
$
|
1187 |
//return false;
|
1188 |
break;
|
1189 |
}
|
@@ -1319,9 +1326,9 @@ class getid3_asf extends getid3_handler {
|
|
1319 |
default:
|
1320 |
// Implementations shall ignore any standard or non-standard object that they do not know how to handle.
|
1321 |
if ($this->GUIDname($NextObjectGUIDtext)) {
|
1322 |
-
$
|
1323 |
} else {
|
1324 |
-
$
|
1325 |
}
|
1326 |
$this->fseek(($NextObjectSize - 16 - 8), SEEK_CUR);
|
1327 |
break;
|
@@ -1405,7 +1412,7 @@ class getid3_asf extends getid3_handler {
|
|
1405 |
break;
|
1406 |
|
1407 |
default:
|
1408 |
-
$
|
1409 |
break;
|
1410 |
|
1411 |
}
|
@@ -1440,6 +1447,11 @@ class getid3_asf extends getid3_handler {
|
|
1440 |
return true;
|
1441 |
}
|
1442 |
|
|
|
|
|
|
|
|
|
|
|
1443 |
public static function codecListObjectTypeLookup($CodecListType) {
|
1444 |
static $lookup = array(
|
1445 |
0x0001 => 'Video Codec',
|
@@ -1450,6 +1462,9 @@ class getid3_asf extends getid3_handler {
|
|
1450 |
return (isset($lookup[$CodecListType]) ? $lookup[$CodecListType] : 'Invalid Codec Type');
|
1451 |
}
|
1452 |
|
|
|
|
|
|
|
1453 |
public static function KnownGUIDs() {
|
1454 |
static $GUIDarray = array(
|
1455 |
'GETID3_ASF_Extended_Stream_Properties_Object' => '14E6A5CB-C672-4332-8399-A96952065B5A',
|
@@ -1564,6 +1579,11 @@ class getid3_asf extends getid3_handler {
|
|
1564 |
return $GUIDarray;
|
1565 |
}
|
1566 |
|
|
|
|
|
|
|
|
|
|
|
1567 |
public static function GUIDname($GUIDstring) {
|
1568 |
static $GUIDarray = array();
|
1569 |
if (empty($GUIDarray)) {
|
@@ -1572,6 +1592,11 @@ class getid3_asf extends getid3_handler {
|
|
1572 |
return array_search($GUIDstring, $GUIDarray);
|
1573 |
}
|
1574 |
|
|
|
|
|
|
|
|
|
|
|
1575 |
public static function ASFIndexObjectIndexTypeLookup($id) {
|
1576 |
static $ASFIndexObjectIndexTypeLookup = array();
|
1577 |
if (empty($ASFIndexObjectIndexTypeLookup)) {
|
@@ -1582,6 +1607,11 @@ class getid3_asf extends getid3_handler {
|
|
1582 |
return (isset($ASFIndexObjectIndexTypeLookup[$id]) ? $ASFIndexObjectIndexTypeLookup[$id] : 'invalid');
|
1583 |
}
|
1584 |
|
|
|
|
|
|
|
|
|
|
|
1585 |
public static function GUIDtoBytestring($GUIDstring) {
|
1586 |
// Microsoft defines these 16-byte (128-bit) GUIDs in the strangest way:
|
1587 |
// first 4 bytes are in little-endian order
|
@@ -1617,6 +1647,11 @@ class getid3_asf extends getid3_handler {
|
|
1617 |
return $hexbytecharstring;
|
1618 |
}
|
1619 |
|
|
|
|
|
|
|
|
|
|
|
1620 |
public static function BytestringToGUID($Bytestring) {
|
1621 |
$GUIDstring = str_pad(dechex(ord($Bytestring{3})), 2, '0', STR_PAD_LEFT);
|
1622 |
$GUIDstring .= str_pad(dechex(ord($Bytestring{2})), 2, '0', STR_PAD_LEFT);
|
@@ -1642,6 +1677,12 @@ class getid3_asf extends getid3_handler {
|
|
1642 |
return strtoupper($GUIDstring);
|
1643 |
}
|
1644 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1645 |
public static function FILETIMEtoUNIXtime($FILETIME, $round=true) {
|
1646 |
// FILETIME is a 64-bit unsigned integer representing
|
1647 |
// the number of 100-nanosecond intervals since January 1, 1601
|
@@ -1653,6 +1694,11 @@ class getid3_asf extends getid3_handler {
|
|
1653 |
return ($FILETIME - 116444736000000000) / 10000000;
|
1654 |
}
|
1655 |
|
|
|
|
|
|
|
|
|
|
|
1656 |
public static function WMpictureTypeLookup($WMpictureType) {
|
1657 |
static $lookup = null;
|
1658 |
if ($lookup === null) {
|
@@ -1684,6 +1730,12 @@ class getid3_asf extends getid3_handler {
|
|
1684 |
return (isset($lookup[$WMpictureType]) ? $lookup[$WMpictureType] : '');
|
1685 |
}
|
1686 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1687 |
public function HeaderExtensionObjectDataParse(&$asf_header_extension_object_data, &$unhandled_sections) {
|
1688 |
// http://msdn.microsoft.com/en-us/library/bb643323.aspx
|
1689 |
|
@@ -1917,9 +1969,9 @@ class getid3_asf extends getid3_handler {
|
|
1917 |
default:
|
1918 |
$unhandled_sections++;
|
1919 |
if ($this->GUIDname($thisObject['guid_text'])) {
|
1920 |
-
$this->
|
1921 |
} else {
|
1922 |
-
$this->
|
1923 |
}
|
1924 |
break;
|
1925 |
}
|
@@ -1930,7 +1982,11 @@ class getid3_asf extends getid3_handler {
|
|
1930 |
return $HeaderExtensionObjectParsed;
|
1931 |
}
|
1932 |
|
1933 |
-
|
|
|
|
|
|
|
|
|
1934 |
public static function metadataLibraryObjectDataTypeLookup($id) {
|
1935 |
static $lookup = array(
|
1936 |
0x0000 => 'Unicode string', // The data consists of a sequence of Unicode characters
|
@@ -1944,6 +2000,11 @@ class getid3_asf extends getid3_handler {
|
|
1944 |
return (isset($lookup[$id]) ? $lookup[$id] : 'invalid');
|
1945 |
}
|
1946 |
|
|
|
|
|
|
|
|
|
|
|
1947 |
public function ASF_WMpicture(&$data) {
|
1948 |
//typedef struct _WMPicture{
|
1949 |
// LPWSTR pwszMIMEType;
|
@@ -1994,14 +2055,24 @@ class getid3_asf extends getid3_handler {
|
|
1994 |
return $WMpicture;
|
1995 |
}
|
1996 |
|
1997 |
-
|
1998 |
-
|
|
|
|
|
|
|
|
|
|
|
1999 |
public static function TrimConvert($string) {
|
2000 |
return trim(getid3_lib::iconv_fallback('UTF-16LE', 'ISO-8859-1', self::TrimTerm($string)), ' ');
|
2001 |
}
|
2002 |
|
2003 |
-
|
2004 |
-
|
|
|
|
|
|
|
|
|
|
|
2005 |
public static function TrimTerm($string) {
|
2006 |
// remove terminator, only if present (it should be, but...)
|
2007 |
if (substr($string, -2) === "\x00\x00") {
|
1 |
<?php
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
5 |
+
// or https://www.getid3.org //
|
6 |
+
// or http://getid3.sourceforge.net //
|
7 |
+
// see readme.txt for more details //
|
|
|
8 |
/////////////////////////////////////////////////////////////////
|
9 |
// //
|
10 |
// module.audio-video.asf.php //
|
15 |
|
16 |
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
|
17 |
|
18 |
+
class getid3_asf extends getid3_handler
|
19 |
+
{
|
20 |
+
/**
|
21 |
+
* @param getID3 $getid3
|
22 |
+
*/
|
23 |
public function __construct(getID3 $getid3) {
|
24 |
parent::__construct($getid3); // extends getid3_handler::__construct()
|
25 |
|
32 |
}
|
33 |
}
|
34 |
|
35 |
+
/**
|
36 |
+
* @return bool
|
37 |
+
*/
|
38 |
public function Analyze() {
|
39 |
$info = &$this->getid3->info;
|
40 |
|
88 |
$NextObjectOffset = $this->ftell();
|
89 |
$ASFHeaderData = $this->fread($thisfile_asf_headerobject['objectsize'] - 30);
|
90 |
$offset = 0;
|
91 |
+
$thisfile_asf_streambitratepropertiesobject = array();
|
92 |
+
$thisfile_asf_codeclistobject = array();
|
93 |
|
94 |
for ($HeaderObjectsCounter = 0; $HeaderObjectsCounter < $thisfile_asf_headerobject['headerobjects']; $HeaderObjectsCounter++) {
|
95 |
$NextObjectGUID = substr($ASFHeaderData, $offset, 16);
|
273 |
$offset += 16;
|
274 |
$thisfile_asf_headerextensionobject['reserved_1_guid'] = $this->BytestringToGUID($thisfile_asf_headerextensionobject['reserved_1']);
|
275 |
if ($thisfile_asf_headerextensionobject['reserved_1'] != GETID3_ASF_Reserved_1) {
|
276 |
+
$this->warning('header_extension_object.reserved_1 GUID ('.$this->BytestringToGUID($thisfile_asf_headerextensionobject['reserved_1']).') does not match expected "GETID3_ASF_Reserved_1" GUID ('.$this->BytestringToGUID(GETID3_ASF_Reserved_1).')');
|
277 |
//return false;
|
278 |
break;
|
279 |
}
|
280 |
$thisfile_asf_headerextensionobject['reserved_2'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
|
281 |
$offset += 2;
|
282 |
if ($thisfile_asf_headerextensionobject['reserved_2'] != 6) {
|
283 |
+
$this->warning('header_extension_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_headerextensionobject['reserved_2']).') does not match expected value of "6"');
|
284 |
//return false;
|
285 |
break;
|
286 |
}
|
323 |
$offset += 16;
|
324 |
$thisfile_asf_codeclistobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_codeclistobject['reserved']);
|
325 |
if ($thisfile_asf_codeclistobject['reserved'] != $this->GUIDtoBytestring('86D15241-311D-11D0-A3A4-00A0C90348F6')) {
|
326 |
+
$this->warning('codec_list_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_codeclistobject['reserved']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {86D15241-311D-11D0-A3A4-00A0C90348F6}');
|
327 |
//return false;
|
328 |
break;
|
329 |
}
|
356 |
if ($thisfile_asf_codeclistobject_codecentries_current['type_raw'] == 2) { // audio codec
|
357 |
|
358 |
if (strpos($thisfile_asf_codeclistobject_codecentries_current['description'], ',') === false) {
|
359 |
+
$this->warning('[asf][codec_list_object][codec_entries]['.$CodecEntryCounter.'][description] expected to contain comma-separated list of parameters: "'.$thisfile_asf_codeclistobject_codecentries_current['description'].'"');
|
360 |
} else {
|
361 |
|
362 |
list($AudioCodecBitrate, $AudioCodecFrequency, $AudioCodecChannels) = explode(',', $this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description']));
|
419 |
break;
|
420 |
|
421 |
default:
|
422 |
+
$this->warning('unknown frequency: "'.$AudioCodecFrequency.'" ('.$this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description']).')');
|
423 |
break;
|
424 |
}
|
425 |
|
465 |
$offset += 16;
|
466 |
$thisfile_asf_scriptcommandobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_scriptcommandobject['reserved']);
|
467 |
if ($thisfile_asf_scriptcommandobject['reserved'] != $this->GUIDtoBytestring('4B1ACBE3-100B-11D0-A39B-00A0C90348F6')) {
|
468 |
+
$this->warning('script_command_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_scriptcommandobject['reserved']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4B1ACBE3-100B-11D0-A39B-00A0C90348F6}');
|
469 |
//return false;
|
470 |
break;
|
471 |
}
|
524 |
$offset += 16;
|
525 |
$thisfile_asf_markerobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_markerobject['reserved']);
|
526 |
if ($thisfile_asf_markerobject['reserved'] != $this->GUIDtoBytestring('4CFEDB20-75F6-11CF-9C0F-00A0C90349CB')) {
|
527 |
+
$this->warning('marker_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_markerobject['reserved_1']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4CFEDB20-75F6-11CF-9C0F-00A0C90349CB}');
|
528 |
break;
|
529 |
}
|
530 |
$thisfile_asf_markerobject['markers_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
|
532 |
$thisfile_asf_markerobject['reserved_2'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
|
533 |
$offset += 2;
|
534 |
if ($thisfile_asf_markerobject['reserved_2'] != 0) {
|
535 |
+
$this->warning('marker_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_markerobject['reserved_2']).') does not match expected value of "0"');
|
536 |
break;
|
537 |
}
|
538 |
$thisfile_asf_markerobject['name_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
|
583 |
$thisfile_asf_bitratemutualexclusionobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_bitratemutualexclusionobject['reserved']);
|
584 |
$offset += 16;
|
585 |
if (($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Bitrate) && ($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Unknown)) {
|
586 |
+
$this->warning('bitrate_mutual_exclusion_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_bitratemutualexclusionobject['reserved']).'} does not match expected "GETID3_ASF_Mutex_Bitrate" GUID {'.$this->BytestringToGUID(GETID3_ASF_Mutex_Bitrate).'} or "GETID3_ASF_Mutex_Unknown" GUID {'.$this->BytestringToGUID(GETID3_ASF_Mutex_Unknown).'}');
|
587 |
//return false;
|
588 |
break;
|
589 |
}
|
644 |
break;
|
645 |
|
646 |
default:
|
647 |
+
$this->warning('error_correction_object.error_correction_type GUID {'.$this->BytestringToGUID($thisfile_asf_errorcorrectionobject['reserved']).'} does not match expected "GETID3_ASF_No_Error_Correction" GUID {'.$this->BytestringToGUID(GETID3_ASF_No_Error_Correction).'} or "GETID3_ASF_Audio_Spread" GUID {'.$this->BytestringToGUID(GETID3_ASF_Audio_Spread).'}');
|
648 |
//return false;
|
649 |
break;
|
650 |
}
|
768 |
break;
|
769 |
|
770 |
default:
|
771 |
+
$this->warning('extended_content_description.content_descriptors.'.$ExtendedContentDescriptorsCounter.'.value_type is invalid ('.$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type'].')');
|
772 |
//return false;
|
773 |
break;
|
774 |
}
|
969 |
default:
|
970 |
// Implementations shall ignore any standard or non-standard object that they do not know how to handle.
|
971 |
if ($this->GUIDname($NextObjectGUIDtext)) {
|
972 |
+
$this->warning('unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8));
|
973 |
} else {
|
974 |
+
$this->warning('unknown GUID {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8));
|
975 |
}
|
976 |
$offset += ($NextObjectSize - 16 - 8);
|
977 |
break;
|
978 |
}
|
979 |
}
|
980 |
+
if (isset($thisfile_asf_streambitratepropertiesobject['bitrate_records_count'])) {
|
981 |
$ASFbitrateAudio = 0;
|
982 |
$ASFbitrateVideo = 0;
|
983 |
+
for ($BitrateRecordsCounter = 0; $BitrateRecordsCounter < $thisfile_asf_streambitratepropertiesobject['bitrate_records_count']; $BitrateRecordsCounter++) {
|
984 |
if (isset($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter])) {
|
985 |
switch ($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter]['type_raw']) {
|
986 |
case 1:
|
987 |
+
$ASFbitrateVideo += $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['bitrate'];
|
988 |
break;
|
989 |
|
990 |
case 2:
|
991 |
+
$ASFbitrateAudio += $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['bitrate'];
|
992 |
break;
|
993 |
|
994 |
default:
|
1190 |
$thisfile_asf_dataobject['reserved'] = getid3_lib::LittleEndian2Int(substr($DataObjectData, $offset, 2));
|
1191 |
$offset += 2;
|
1192 |
if ($thisfile_asf_dataobject['reserved'] != 0x0101) {
|
1193 |
+
$this->warning('data_object.reserved ('.getid3_lib::PrintHexBytes($thisfile_asf_dataobject['reserved']).') does not match expected value of "0x0101"');
|
1194 |
//return false;
|
1195 |
break;
|
1196 |
}
|
1326 |
default:
|
1327 |
// Implementations shall ignore any standard or non-standard object that they do not know how to handle.
|
1328 |
if ($this->GUIDname($NextObjectGUIDtext)) {
|
1329 |
+
$this->warning('unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF body at offset '.($offset - 16 - 8));
|
1330 |
} else {
|
1331 |
+
$this->warning('unknown GUID {'.$NextObjectGUIDtext.'} in ASF body at offset '.($this->ftell() - 16 - 8));
|
1332 |
}
|
1333 |
$this->fseek(($NextObjectSize - 16 - 8), SEEK_CUR);
|
1334 |
break;
|
1412 |
break;
|
1413 |
|
1414 |
default:
|
1415 |
+
$this->warning('Unknown streamtype: [codec_list_object][codec_entries]['.$streamnumber.'][type_raw] == '.$streamdata['type_raw']);
|
1416 |
break;
|
1417 |
|
1418 |
}
|
1447 |
return true;
|
1448 |
}
|
1449 |
|
1450 |
+
/**
|
1451 |
+
* @param int $CodecListType
|
1452 |
+
*
|
1453 |
+
* @return string
|
1454 |
+
*/
|
1455 |
public static function codecListObjectTypeLookup($CodecListType) {
|
1456 |
static $lookup = array(
|
1457 |
0x0001 => 'Video Codec',
|
1462 |
return (isset($lookup[$CodecListType]) ? $lookup[$CodecListType] : 'Invalid Codec Type');
|
1463 |
}
|
1464 |
|
1465 |
+
/**
|
1466 |
+
* @return array
|
1467 |
+
*/
|
1468 |
public static function KnownGUIDs() {
|
1469 |
static $GUIDarray = array(
|
1470 |
'GETID3_ASF_Extended_Stream_Properties_Object' => '14E6A5CB-C672-4332-8399-A96952065B5A',
|
1579 |
return $GUIDarray;
|
1580 |
}
|
1581 |
|
1582 |
+
/**
|
1583 |
+
* @param string $GUIDstring
|
1584 |
+
*
|
1585 |
+
* @return string|false
|
1586 |
+
*/
|
1587 |
public static function GUIDname($GUIDstring) {
|
1588 |
static $GUIDarray = array();
|
1589 |
if (empty($GUIDarray)) {
|
1592 |
return array_search($GUIDstring, $GUIDarray);
|
1593 |
}
|
1594 |
|
1595 |
+
/**
|
1596 |
+
* @param int $id
|
1597 |
+
*
|
1598 |
+
* @return string
|
1599 |
+
*/
|
1600 |
public static function ASFIndexObjectIndexTypeLookup($id) {
|
1601 |
static $ASFIndexObjectIndexTypeLookup = array();
|
1602 |
if (empty($ASFIndexObjectIndexTypeLookup)) {
|
1607 |
return (isset($ASFIndexObjectIndexTypeLookup[$id]) ? $ASFIndexObjectIndexTypeLookup[$id] : 'invalid');
|
1608 |
}
|
1609 |
|
1610 |
+
/**
|
1611 |
+
* @param string $GUIDstring
|
1612 |
+
*
|
1613 |
+
* @return string
|
1614 |
+
*/
|
1615 |
public static function GUIDtoBytestring($GUIDstring) {
|
1616 |
// Microsoft defines these 16-byte (128-bit) GUIDs in the strangest way:
|
1617 |
// first 4 bytes are in little-endian order
|
1647 |
return $hexbytecharstring;
|
1648 |
}
|
1649 |
|
1650 |
+
/**
|
1651 |
+
* @param string $Bytestring
|
1652 |
+
*
|
1653 |
+
* @return string
|
1654 |
+
*/
|
1655 |
public static function BytestringToGUID($Bytestring) {
|
1656 |
$GUIDstring = str_pad(dechex(ord($Bytestring{3})), 2, '0', STR_PAD_LEFT);
|
1657 |
$GUIDstring .= str_pad(dechex(ord($Bytestring{2})), 2, '0', STR_PAD_LEFT);
|
1677 |
return strtoupper($GUIDstring);
|
1678 |
}
|
1679 |
|
1680 |
+
/**
|
1681 |
+
* @param int $FILETIME
|
1682 |
+
* @param bool $round
|
1683 |
+
*
|
1684 |
+
* @return float|int
|
1685 |
+
*/
|
1686 |
public static function FILETIMEtoUNIXtime($FILETIME, $round=true) {
|
1687 |
// FILETIME is a 64-bit unsigned integer representing
|
1688 |
// the number of 100-nanosecond intervals since January 1, 1601
|
1694 |
return ($FILETIME - 116444736000000000) / 10000000;
|
1695 |
}
|
1696 |
|
1697 |
+
/**
|
1698 |
+
* @param int $WMpictureType
|
1699 |
+
*
|
1700 |
+
* @return string
|
1701 |
+
*/
|
1702 |
public static function WMpictureTypeLookup($WMpictureType) {
|
1703 |
static $lookup = null;
|
1704 |
if ($lookup === null) {
|
1730 |
return (isset($lookup[$WMpictureType]) ? $lookup[$WMpictureType] : '');
|
1731 |
}
|
1732 |
|
1733 |
+
/**
|
1734 |
+
* @param string $asf_header_extension_object_data
|
1735 |
+
* @param int $unhandled_sections
|
1736 |
+
*
|
1737 |
+
* @return array
|
1738 |
+
*/
|
1739 |
public function HeaderExtensionObjectDataParse(&$asf_header_extension_object_data, &$unhandled_sections) {
|
1740 |
// http://msdn.microsoft.com/en-us/library/bb643323.aspx
|
1741 |
|
1969 |
default:
|
1970 |
$unhandled_sections++;
|
1971 |
if ($this->GUIDname($thisObject['guid_text'])) {
|
1972 |
+
$this->warning('unhandled Header Extension Object GUID "'.$this->GUIDname($thisObject['guid_text']).'" {'.$thisObject['guid_text'].'} at offset '.($offset - 16 - 8));
|
1973 |
} else {
|
1974 |
+
$this->warning('unknown Header Extension Object GUID {'.$thisObject['guid_text'].'} in at offset '.($offset - 16 - 8));
|
1975 |
}
|
1976 |
break;
|
1977 |
}
|
1982 |
return $HeaderExtensionObjectParsed;
|
1983 |
}
|
1984 |
|
1985 |
+
/**
|
1986 |
+
* @param int $id
|
1987 |
+
*
|
1988 |
+
* @return string
|
1989 |
+
*/
|
1990 |
public static function metadataLibraryObjectDataTypeLookup($id) {
|
1991 |
static $lookup = array(
|
1992 |
0x0000 => 'Unicode string', // The data consists of a sequence of Unicode characters
|
2000 |
return (isset($lookup[$id]) ? $lookup[$id] : 'invalid');
|
2001 |
}
|
2002 |
|
2003 |
+
/**
|
2004 |
+
* @param string $data
|
2005 |
+
*
|
2006 |
+
* @return array
|
2007 |
+
*/
|
2008 |
public function ASF_WMpicture(&$data) {
|
2009 |
//typedef struct _WMPicture{
|
2010 |
// LPWSTR pwszMIMEType;
|
2055 |
return $WMpicture;
|
2056 |
}
|
2057 |
|
2058 |
+
/**
|
2059 |
+
* Remove terminator 00 00 and convert UTF-16LE to Latin-1.
|
2060 |
+
*
|
2061 |
+
* @param string $string
|
2062 |
+
*
|
2063 |
+
* @return string
|
2064 |
+
*/
|
2065 |
public static function TrimConvert($string) {
|
2066 |
return trim(getid3_lib::iconv_fallback('UTF-16LE', 'ISO-8859-1', self::TrimTerm($string)), ' ');
|
2067 |
}
|
2068 |
|
2069 |
+
/**
|
2070 |
+
* Remove terminator 00 00.
|
2071 |
+
*
|
2072 |
+
* @param string $string
|
2073 |
+
*
|
2074 |
+
* @return string
|
2075 |
+
*/
|
2076 |
public static function TrimTerm($string) {
|
2077 |
// remove terminator, only if present (it should be, but...)
|
2078 |
if (substr($string, -2) === "\x00\x00") {
|
lib/getid3/module.audio-video.bink.php
CHANGED
@@ -1,11 +1,10 @@
|
|
1 |
<?php
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.bink.php //
|
@@ -17,11 +16,13 @@
|
|
17 |
|
18 |
class getid3_bink extends getid3_handler
|
19 |
{
|
20 |
-
|
|
|
|
|
21 |
public function Analyze() {
|
22 |
$info = &$this->getid3->info;
|
23 |
|
24 |
-
$
|
25 |
|
26 |
$this->fseek($info['avdataoffset']);
|
27 |
$fileTypeID = $this->fread(3);
|
@@ -35,7 +36,7 @@ $info['error'][] = 'Bink / Smacker files not properly processed by this version
|
|
35 |
break;
|
36 |
|
37 |
default:
|
38 |
-
$
|
39 |
return false;
|
40 |
break;
|
41 |
}
|
@@ -44,6 +45,9 @@ $info['error'][] = 'Bink / Smacker files not properly processed by this version
|
|
44 |
|
45 |
}
|
46 |
|
|
|
|
|
|
|
47 |
public function ParseBink() {
|
48 |
$info = &$this->getid3->info;
|
49 |
$info['fileformat'] = 'bink';
|
@@ -55,12 +59,15 @@ $info['error'][] = 'Bink / Smacker files not properly processed by this version
|
|
55 |
$info['bink']['frame_count'] = getid3_lib::LittleEndian2Int(substr($fileData, 8, 2));
|
56 |
|
57 |
if (($info['avdataend'] - $info['avdataoffset']) != ($info['bink']['data_size'] + 8)) {
|
58 |
-
$
|
59 |
}
|
60 |
|
61 |
return true;
|
62 |
}
|
63 |
|
|
|
|
|
|
|
64 |
public function ParseSmacker() {
|
65 |
$info = &$this->getid3->info;
|
66 |
$info['fileformat'] = 'smacker';
|
1 |
<?php
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
5 |
+
// or https://www.getid3.org //
|
6 |
+
// or http://getid3.sourceforge.net //
|
7 |
+
// see readme.txt for more details //
|
|
|
8 |
/////////////////////////////////////////////////////////////////
|
9 |
// //
|
10 |
// module.audio.bink.php //
|
16 |
|
17 |
class getid3_bink extends getid3_handler
|
18 |
{
|
19 |
+
/**
|
20 |
+
* @return bool
|
21 |
+
*/
|
22 |
public function Analyze() {
|
23 |
$info = &$this->getid3->info;
|
24 |
|
25 |
+
$this->error('Bink / Smacker files not properly processed by this version of getID3() ['.$this->getid3->version().']');
|
26 |
|
27 |
$this->fseek($info['avdataoffset']);
|
28 |
$fileTypeID = $this->fread(3);
|
36 |
break;
|
37 |
|
38 |
default:
|
39 |
+
$this->error('Expecting "BIK" or "SMK" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($fileTypeID).'"');
|
40 |
return false;
|
41 |
break;
|
42 |
}
|
45 |
|
46 |
}
|
47 |
|
48 |
+
/**
|
49 |
+
* @return bool
|
50 |
+
*/
|
51 |
public function ParseBink() {
|
52 |
$info = &$this->getid3->info;
|
53 |
$info['fileformat'] = 'bink';
|
59 |
$info['bink']['frame_count'] = getid3_lib::LittleEndian2Int(substr($fileData, 8, 2));
|
60 |
|
61 |
if (($info['avdataend'] - $info['avdataoffset']) != ($info['bink']['data_size'] + 8)) {
|
62 |
+
$this->error('Probably truncated file: expecting '.$info['bink']['data_size'].' bytes, found '.($info['avdataend'] - $info['avdataoffset']));
|
63 |
}
|
64 |
|
65 |
return true;
|
66 |
}
|
67 |
|
68 |
+
/**
|
69 |
+
* @return bool
|
70 |
+
*/
|
71 |
public function ParseSmacker() {
|
72 |
$info = &$this->getid3->info;
|
73 |
$info['fileformat'] = 'smacker';
|
lib/getid3/module.audio-video.flv.php
CHANGED
@@ -1,15 +1,22 @@
|
|
1 |
<?php
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
// //
|
8 |
// FLV module by Seth Kaufman <sethØwhirl-i-gig*com> //
|
9 |
// //
|
10 |
// * version 0.1 (26 June 2005) //
|
11 |
// //
|
12 |
-
// //
|
13 |
// * version 0.1.1 (15 July 2005) //
|
14 |
// minor modifications by James Heinrich <info@getid3.org> //
|
15 |
// //
|
@@ -43,12 +50,6 @@
|
|
43 |
// handle GETID3_FLV_VIDEO_VP6FLV_ALPHA //
|
44 |
// improved AVCSequenceParameterSetReader::readData() //
|
45 |
// by Xander Schouwerwou <schouwerwouØgmail*com> //
|
46 |
-
// //
|
47 |
-
/////////////////////////////////////////////////////////////////
|
48 |
-
// //
|
49 |
-
// module.audio-video.flv.php //
|
50 |
-
// module for analyzing Shockwave Flash Video files //
|
51 |
-
// dependencies: NONE //
|
52 |
// ///
|
53 |
/////////////////////////////////////////////////////////////////
|
54 |
|
@@ -73,12 +74,21 @@ define('H264_PROFILE_HIGH422', 122);
|
|
73 |
define('H264_PROFILE_HIGH444', 144);
|
74 |
define('H264_PROFILE_HIGH444_PREDICTIVE', 244);
|
75 |
|
76 |
-
class getid3_flv extends getid3_handler
|
77 |
-
|
78 |
const magic = 'FLV';
|
79 |
|
80 |
-
|
81 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
public function Analyze() {
|
83 |
$info = &$this->getid3->info;
|
84 |
|
@@ -93,7 +103,7 @@ class getid3_flv extends getid3_handler {
|
|
93 |
$TypeFlags = getid3_lib::BigEndian2Int(substr($FLVheader, 4, 1));
|
94 |
|
95 |
if ($info['flv']['header']['signature'] != self::magic) {
|
96 |
-
$
|
97 |
unset($info['flv'], $info['fileformat']);
|
98 |
return false;
|
99 |
}
|
@@ -332,7 +342,11 @@ class getid3_flv extends getid3_handler {
|
|
332 |
return true;
|
333 |
}
|
334 |
|
335 |
-
|
|
|
|
|
|
|
|
|
336 |
public static function audioFormatLookup($id) {
|
337 |
static $lookup = array(
|
338 |
0 => 'Linear PCM, platform endian',
|
@@ -355,6 +369,11 @@ class getid3_flv extends getid3_handler {
|
|
355 |
return (isset($lookup[$id]) ? $lookup[$id] : false);
|
356 |
}
|
357 |
|
|
|
|
|
|
|
|
|
|
|
358 |
public static function audioRateLookup($id) {
|
359 |
static $lookup = array(
|
360 |
0 => 5500,
|
@@ -365,6 +384,11 @@ class getid3_flv extends getid3_handler {
|
|
365 |
return (isset($lookup[$id]) ? $lookup[$id] : false);
|
366 |
}
|
367 |
|
|
|
|
|
|
|
|
|
|
|
368 |
public static function audioBitDepthLookup($id) {
|
369 |
static $lookup = array(
|
370 |
0 => 8,
|
@@ -373,6 +397,11 @@ class getid3_flv extends getid3_handler {
|
|
373 |
return (isset($lookup[$id]) ? $lookup[$id] : false);
|
374 |
}
|
375 |
|
|
|
|
|
|
|
|
|
|
|
376 |
public static function videoCodecLookup($id) {
|
377 |
static $lookup = array(
|
378 |
GETID3_FLV_VIDEO_H263 => 'Sorenson H.263',
|
@@ -386,47 +415,84 @@ class getid3_flv extends getid3_handler {
|
|
386 |
}
|
387 |
}
|
388 |
|
389 |
-
class AMFStream
|
|
|
|
|
|
|
|
|
390 |
public $bytes;
|
|
|
|
|
|
|
|
|
391 |
public $pos;
|
392 |
|
|
|
|
|
|
|
393 |
public function __construct(&$bytes) {
|
394 |
$this->bytes =& $bytes;
|
395 |
$this->pos = 0;
|
396 |
}
|
397 |
|
398 |
-
|
399 |
-
|
|
|
|
|
|
|
400 |
}
|
401 |
|
402 |
-
|
|
|
|
|
|
|
403 |
return ($this->readByte() << 8) + $this->readByte();
|
404 |
}
|
405 |
|
406 |
-
|
|
|
|
|
|
|
407 |
return ($this->readByte() << 24) + ($this->readByte() << 16) + ($this->readByte() << 8) + $this->readByte();
|
408 |
}
|
409 |
|
|
|
|
|
|
|
410 |
public function readDouble() {
|
411 |
return getid3_lib::BigEndian2Float($this->read(8));
|
412 |
}
|
413 |
|
|
|
|
|
|
|
414 |
public function readUTF() {
|
415 |
$length = $this->readInt();
|
416 |
return $this->read($length);
|
417 |
}
|
418 |
|
|
|
|
|
|
|
419 |
public function readLongUTF() {
|
420 |
$length = $this->readLong();
|
421 |
return $this->read($length);
|
422 |
}
|
423 |
|
|
|
|
|
|
|
|
|
|
|
424 |
public function read($length) {
|
425 |
$val = substr($this->bytes, $this->pos, $length);
|
426 |
$this->pos += $length;
|
427 |
return $val;
|
428 |
}
|
429 |
|
|
|
|
|
|
|
430 |
public function peekByte() {
|
431 |
$pos = $this->pos;
|
432 |
$val = $this->readByte();
|
@@ -434,6 +500,9 @@ class AMFStream {
|
|
434 |
return $val;
|
435 |
}
|
436 |
|
|
|
|
|
|
|
437 |
public function peekInt() {
|
438 |
$pos = $this->pos;
|
439 |
$val = $this->readInt();
|
@@ -441,6 +510,9 @@ class AMFStream {
|
|
441 |
return $val;
|
442 |
}
|
443 |
|
|
|
|
|
|
|
444 |
public function peekLong() {
|
445 |
$pos = $this->pos;
|
446 |
$val = $this->readLong();
|
@@ -448,6 +520,9 @@ class AMFStream {
|
|
448 |
return $val;
|
449 |
}
|
450 |
|
|
|
|
|
|
|
451 |
public function peekDouble() {
|
452 |
$pos = $this->pos;
|
453 |
$val = $this->readDouble();
|
@@ -455,6 +530,9 @@ class AMFStream {
|
|
455 |
return $val;
|
456 |
}
|
457 |
|
|
|
|
|
|
|
458 |
public function peekUTF() {
|
459 |
$pos = $this->pos;
|
460 |
$val = $this->readUTF();
|
@@ -462,6 +540,9 @@ class AMFStream {
|
|
462 |
return $val;
|
463 |
}
|
464 |
|
|
|
|
|
|
|
465 |
public function peekLongUTF() {
|
466 |
$pos = $this->pos;
|
467 |
$val = $this->readLongUTF();
|
@@ -470,13 +551,23 @@ class AMFStream {
|
|
470 |
}
|
471 |
}
|
472 |
|
473 |
-
class AMFReader
|
|
|
|
|
|
|
|
|
474 |
public $stream;
|
475 |
|
476 |
-
|
477 |
-
|
|
|
|
|
|
|
478 |
}
|
479 |
|
|
|
|
|
|
|
480 |
public function readData() {
|
481 |
$value = null;
|
482 |
|
@@ -547,23 +638,36 @@ class AMFReader {
|
|
547 |
return $value;
|
548 |
}
|
549 |
|
|
|
|
|
|
|
550 |
public function readDouble() {
|
551 |
return $this->stream->readDouble();
|
552 |
}
|
553 |
|
|
|
|
|
|
|
554 |
public function readBoolean() {
|
555 |
return $this->stream->readByte() == 1;
|
556 |
}
|
557 |
|
|
|
|
|
|
|
558 |
public function readString() {
|
559 |
return $this->stream->readUTF();
|
560 |
}
|
561 |
|
|
|
|
|
|
|
562 |
public function readObject() {
|
563 |
// Get highest numerical index - ignored
|
564 |
// $highestIndex = $this->stream->readLong();
|
565 |
|
566 |
$data = array();
|
|
|
567 |
|
568 |
while ($key = $this->stream->readUTF()) {
|
569 |
$data[$key] = $this->readData();
|
@@ -576,15 +680,19 @@ class AMFReader {
|
|
576 |
return $data;
|
577 |
}
|
578 |
|
|
|
|
|
|
|
579 |
public function readMixedArray() {
|
580 |
// Get highest numerical index - ignored
|
581 |
$highestIndex = $this->stream->readLong();
|
582 |
|
583 |
$data = array();
|
|
|
584 |
|
585 |
while ($key = $this->stream->readUTF()) {
|
586 |
if (is_numeric($key)) {
|
587 |
-
$key = (
|
588 |
}
|
589 |
$data[$key] = $this->readData();
|
590 |
}
|
@@ -597,6 +705,9 @@ class AMFReader {
|
|
597 |
return $data;
|
598 |
}
|
599 |
|
|
|
|
|
|
|
600 |
public function readArray() {
|
601 |
$length = $this->stream->readLong();
|
602 |
$data = array();
|
@@ -607,34 +718,61 @@ class AMFReader {
|
|
607 |
return $data;
|
608 |
}
|
609 |
|
|
|
|
|
|
|
610 |
public function readDate() {
|
611 |
$timestamp = $this->stream->readDouble();
|
612 |
$timezone = $this->stream->readInt();
|
613 |
return $timestamp;
|
614 |
}
|
615 |
|
|
|
|
|
|
|
616 |
public function readLongString() {
|
617 |
return $this->stream->readLongUTF();
|
618 |
}
|
619 |
|
|
|
|
|
|
|
620 |
public function readXML() {
|
621 |
return $this->stream->readLongUTF();
|
622 |
}
|
623 |
|
|
|
|
|
|
|
624 |
public function readTypedObject() {
|
625 |
$className = $this->stream->readUTF();
|
626 |
return $this->readObject();
|
627 |
}
|
628 |
}
|
629 |
|
630 |
-
class AVCSequenceParameterSetReader
|
|
|
|
|
|
|
|
|
631 |
public $sps;
|
632 |
public $start = 0;
|
633 |
public $currentBytes = 0;
|
634 |
public $currentBits = 0;
|
|
|
|
|
|
|
|
|
635 |
public $width;
|
|
|
|
|
|
|
|
|
636 |
public $height;
|
637 |
|
|
|
|
|
|
|
638 |
public function __construct($sps) {
|
639 |
$this->sps = $sps;
|
640 |
}
|
@@ -691,18 +829,29 @@ class AVCSequenceParameterSetReader {
|
|
691 |
}
|
692 |
}
|
693 |
|
|
|
|
|
|
|
694 |
public function skipBits($bits) {
|
695 |
$newBits = $this->currentBits + $bits;
|
696 |
$this->currentBytes += (int)floor($newBits / 8);
|
697 |
$this->currentBits = $newBits % 8;
|
698 |
}
|
699 |
|
|
|
|
|
|
|
700 |
public function getBit() {
|
701 |
$result = (getid3_lib::BigEndian2Int(substr($this->sps, $this->currentBytes, 1)) >> (7 - $this->currentBits)) & 0x01;
|
702 |
$this->skipBits(1);
|
703 |
return $result;
|
704 |
}
|
705 |
|
|
|
|
|
|
|
|
|
|
|
706 |
public function getBits($bits) {
|
707 |
$result = 0;
|
708 |
for ($i = 0; $i < $bits; $i++) {
|
@@ -711,6 +860,9 @@ class AVCSequenceParameterSetReader {
|
|
711 |
return $result;
|
712 |
}
|
713 |
|
|
|
|
|
|
|
714 |
public function expGolombUe() {
|
715 |
$significantBits = 0;
|
716 |
$bit = $this->getBit();
|
@@ -726,6 +878,9 @@ class AVCSequenceParameterSetReader {
|
|
726 |
return (1 << $significantBits) + $this->getBits($significantBits) - 1;
|
727 |
}
|
728 |
|
|
|
|
|
|
|
729 |
public function expGolombSe() {
|
730 |
$result = $this->expGolombUe();
|
731 |
if (($result & 0x01) == 0) {
|
@@ -735,10 +890,16 @@ class AVCSequenceParameterSetReader {
|
|
735 |
}
|
736 |
}
|
737 |
|
|
|
|
|
|
|
738 |
public function getWidth() {
|
739 |
return $this->width;
|
740 |
}
|
741 |
|
|
|
|
|
|
|
742 |
public function getHeight() {
|
743 |
return $this->height;
|
744 |
}
|
1 |
<?php
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
5 |
+
// or https://www.getid3.org //
|
6 |
+
// or http://getid3.sourceforge.net //
|
7 |
+
// see readme.txt for more details //
|
8 |
+
/////////////////////////////////////////////////////////////////
|
9 |
+
// //
|
10 |
+
// module.audio-video.flv.php //
|
11 |
+
// module for analyzing Shockwave Flash Video files //
|
12 |
+
// dependencies: NONE //
|
13 |
+
// //
|
14 |
+
/////////////////////////////////////////////////////////////////
|
15 |
// //
|
16 |
// FLV module by Seth Kaufman <sethØwhirl-i-gig*com> //
|
17 |
// //
|
18 |
// * version 0.1 (26 June 2005) //
|
19 |
// //
|
|
|
20 |
// * version 0.1.1 (15 July 2005) //
|
21 |
// minor modifications by James Heinrich <info@getid3.org> //
|
22 |
// //
|
50 |
// handle GETID3_FLV_VIDEO_VP6FLV_ALPHA //
|
51 |
// improved AVCSequenceParameterSetReader::readData() //
|
52 |
// by Xander Schouwerwou <schouwerwouØgmail*com> //
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
// ///
|
54 |
/////////////////////////////////////////////////////////////////
|
55 |
|
74 |
define('H264_PROFILE_HIGH444', 144);
|
75 |
define('H264_PROFILE_HIGH444_PREDICTIVE', 244);
|
76 |
|
77 |
+
class getid3_flv extends getid3_handler
|
78 |
+
{
|
79 |
const magic = 'FLV';
|
80 |
|
81 |
+
/**
|
82 |
+
* Break out of the loop if too many frames have been scanned; only scan this
|
83 |
+
* many if meta frame does not contain useful duration.
|
84 |
+
*
|
85 |
+
* @var int
|
86 |
+
*/
|
87 |
+
public $max_frames = 100000;
|
88 |
+
|
89 |
+
/**
|
90 |
+
* @return bool
|
91 |
+
*/
|
92 |
public function Analyze() {
|
93 |
$info = &$this->getid3->info;
|
94 |
|
103 |
$TypeFlags = getid3_lib::BigEndian2Int(substr($FLVheader, 4, 1));
|
104 |
|
105 |
if ($info['flv']['header']['signature'] != self::magic) {
|
106 |
+
$this->error('Expecting "'.getid3_lib::PrintHexBytes(self::magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($info['flv']['header']['signature']).'"');
|
107 |
unset($info['flv'], $info['fileformat']);
|
108 |
return false;
|
109 |
}
|
342 |
return true;
|
343 |
}
|
344 |
|
345 |
+
/**
|
346 |
+
* @param int $id
|
347 |
+
*
|
348 |
+
* @return string|false
|
349 |
+
*/
|
350 |
public static function audioFormatLookup($id) {
|
351 |
static $lookup = array(
|
352 |
0 => 'Linear PCM, platform endian',
|
369 |
return (isset($lookup[$id]) ? $lookup[$id] : false);
|
370 |
}
|
371 |
|
372 |
+
/**
|
373 |
+
* @param int $id
|
374 |
+
*
|
375 |
+
* @return int|false
|
376 |
+
*/
|
377 |
public static function audioRateLookup($id) {
|
378 |
static $lookup = array(
|
379 |
0 => 5500,
|
384 |
return (isset($lookup[$id]) ? $lookup[$id] : false);
|
385 |
}
|
386 |
|
387 |
+
/**
|
388 |
+
* @param int $id
|
389 |
+
*
|
390 |
+
* @return int|false
|
391 |
+
*/
|
392 |
public static function audioBitDepthLookup($id) {
|
393 |
static $lookup = array(
|
394 |
0 => 8,
|
397 |
return (isset($lookup[$id]) ? $lookup[$id] : false);
|
398 |
}
|
399 |
|
400 |
+
/**
|
401 |
+
* @param int $id
|
402 |
+
*
|
403 |
+
* @return string|false
|
404 |
+
*/
|
405 |
public static function videoCodecLookup($id) {
|
406 |
static $lookup = array(
|
407 |
GETID3_FLV_VIDEO_H263 => 'Sorenson H.263',
|
415 |
}
|
416 |
}
|
417 |
|
418 |
+
class AMFStream
|
419 |
+
{
|
420 |
+
/**
|
421 |
+
* @var string
|
422 |
+
*/
|
423 |
public $bytes;
|
424 |
+
|
425 |
+
/**
|
426 |
+
* @var int
|
427 |
+
*/
|
428 |
public $pos;
|
429 |
|
430 |
+
/**
|
431 |
+
* @param string $bytes
|
432 |
+
*/
|
433 |
public function __construct(&$bytes) {
|
434 |
$this->bytes =& $bytes;
|
435 |
$this->pos = 0;
|
436 |
}
|
437 |
|
438 |
+
/**
|
439 |
+
* @return int
|
440 |
+
*/
|
441 |
+
public function readByte() { // 8-bit
|
442 |
+
return ord(substr($this->bytes, $this->pos++, 1));
|
443 |
}
|
444 |
|
445 |
+
/**
|
446 |
+
* @return int
|
447 |
+
*/
|
448 |
+
public function readInt() { // 16-bit
|
449 |
return ($this->readByte() << 8) + $this->readByte();
|
450 |
}
|
451 |
|
452 |
+
/**
|
453 |
+
* @return int
|
454 |
+
*/
|
455 |
+
public function readLong() { // 32-bit
|
456 |
return ($this->readByte() << 24) + ($this->readByte() << 16) + ($this->readByte() << 8) + $this->readByte();
|
457 |
}
|
458 |
|
459 |
+
/**
|
460 |
+
* @return float|false
|
461 |
+
*/
|
462 |
public function readDouble() {
|
463 |
return getid3_lib::BigEndian2Float($this->read(8));
|
464 |
}
|
465 |
|
466 |
+
/**
|
467 |
+
* @return string
|
468 |
+
*/
|
469 |
public function readUTF() {
|
470 |
$length = $this->readInt();
|
471 |
return $this->read($length);
|
472 |
}
|
473 |
|
474 |
+
/**
|
475 |
+
* @return string
|
476 |
+
*/
|
477 |
public function readLongUTF() {
|
478 |
$length = $this->readLong();
|
479 |
return $this->read($length);
|
480 |
}
|
481 |
|
482 |
+
/**
|
483 |
+
* @param int $length
|
484 |
+
*
|
485 |
+
* @return string
|
486 |
+
*/
|
487 |
public function read($length) {
|
488 |
$val = substr($this->bytes, $this->pos, $length);
|
489 |
$this->pos += $length;
|
490 |
return $val;
|
491 |
}
|
492 |
|
493 |
+
/**
|
494 |
+
* @return int
|
495 |
+
*/
|
496 |
public function peekByte() {
|
497 |
$pos = $this->pos;
|
498 |
$val = $this->readByte();
|
500 |
return $val;
|
501 |
}
|
502 |
|
503 |
+
/**
|
504 |
+
* @return int
|
505 |
+
*/
|
506 |
public function peekInt() {
|
507 |
$pos = $this->pos;
|
508 |
$val = $this->readInt();
|
510 |
return $val;
|
511 |
}
|
512 |
|
513 |
+
/**
|
514 |
+
* @return int
|
515 |
+
*/
|
516 |
public function peekLong() {
|
517 |
$pos = $this->pos;
|
518 |
$val = $this->readLong();
|
520 |
return $val;
|
521 |
}
|
522 |
|
523 |
+
/**
|
524 |
+
* @return float|false
|
525 |
+
*/
|
526 |
public function peekDouble() {
|
527 |
$pos = $this->pos;
|
528 |
$val = $this->readDouble();
|
530 |
return $val;
|
531 |
}
|
532 |
|
533 |
+
/**
|
534 |
+
* @return string
|
535 |
+
*/
|
536 |
public function peekUTF() {
|
537 |
$pos = $this->pos;
|
538 |
$val = $this->readUTF();
|
540 |
return $val;
|
541 |
}
|
542 |
|
543 |
+
/**
|
544 |
+
* @return string
|
545 |
+
*/
|
546 |
public function peekLongUTF() {
|
547 |
$pos = $this->pos;
|
548 |
$val = $this->readLongUTF();
|
551 |
}
|
552 |
}
|
553 |
|
554 |
+
class AMFReader
|
555 |
+
{
|
556 |
+
/**
|
557 |
+
* @var AMFStream
|
558 |
+
*/
|
559 |
public $stream;
|
560 |
|
561 |
+
/**
|
562 |
+
* @param AMFStream $stream
|
563 |
+
*/
|
564 |
+
public function __construct(AMFStream $stream) {
|
565 |
+
$this->stream = $stream;
|
566 |
}
|
567 |
|
568 |
+
/**
|
569 |
+
* @return mixed
|
570 |
+
*/
|
571 |
public function readData() {
|
572 |
$value = null;
|
573 |
|
638 |
return $value;
|
639 |
}
|
640 |
|
641 |
+
/**
|
642 |
+
* @return float|false
|
643 |
+
*/
|
644 |
public function readDouble() {
|
645 |
return $this->stream->readDouble();
|
646 |
}
|
647 |
|
648 |
+
/**
|
649 |
+
* @return bool
|
650 |
+
*/
|
651 |
public function readBoolean() {
|
652 |
return $this->stream->readByte() == 1;
|
653 |
}
|
654 |
|
655 |
+
/**
|
656 |
+
* @return string
|
657 |
+
*/
|
658 |
public function readString() {
|
659 |
return $this->stream->readUTF();
|
660 |
}
|
661 |
|
662 |
+
/**
|
663 |
+
* @return array
|
664 |
+
*/
|
665 |
public function readObject() {
|
666 |
// Get highest numerical index - ignored
|
667 |
// $highestIndex = $this->stream->readLong();
|
668 |
|
669 |
$data = array();
|
670 |
+
$key = null;
|
671 |
|
672 |
while ($key = $this->stream->readUTF()) {
|
673 |
$data[$key] = $this->readData();
|
680 |
return $data;
|
681 |
}
|
682 |
|
683 |
+
/**
|
684 |
+
* @return array
|
685 |
+
*/
|
686 |
public function readMixedArray() {
|
687 |
// Get highest numerical index - ignored
|
688 |
$highestIndex = $this->stream->readLong();
|
689 |
|
690 |
$data = array();
|
691 |
+
$key = null;
|
692 |
|
693 |
while ($key = $this->stream->readUTF()) {
|
694 |
if (is_numeric($key)) {
|
695 |
+
$key = (int) $key;
|
696 |
}
|
697 |
$data[$key] = $this->readData();
|
698 |
}
|
705 |
return $data;
|
706 |
}
|
707 |
|
708 |
+
/**
|
709 |
+
* @return array
|
710 |
+
*/
|
711 |
public function readArray() {
|
712 |
$length = $this->stream->readLong();
|
713 |
$data = array();
|
718 |
return $data;
|
719 |
}
|
720 |
|
721 |
+
/**
|
722 |
+
* @return float|false
|
723 |
+
*/
|
724 |
public function readDate() {
|
725 |
$timestamp = $this->stream->readDouble();
|
726 |
$timezone = $this->stream->readInt();
|
727 |
return $timestamp;
|
728 |
}
|
729 |
|
730 |
+
/**
|
731 |
+
* @return string
|
732 |
+
*/
|
733 |
public function readLongString() {
|
734 |
return $this->stream->readLongUTF();
|
735 |
}
|
736 |
|
737 |
+
/**
|
738 |
+
* @return string
|
739 |
+
*/
|
740 |
public function readXML() {
|
741 |
return $this->stream->readLongUTF();
|
742 |
}
|
743 |
|
744 |
+
/**
|
745 |
+
* @return array
|
746 |
+
*/
|
747 |
public function readTypedObject() {
|
748 |
$className = $this->stream->readUTF();
|
749 |
return $this->readObject();
|
750 |
}
|
751 |
}
|
752 |
|
753 |
+
class AVCSequenceParameterSetReader
|
754 |
+
{
|
755 |
+
/**
|
756 |
+
* @var string
|
757 |
+
*/
|
758 |
public $sps;
|
759 |
public $start = 0;
|
760 |
public $currentBytes = 0;
|
761 |
public $currentBits = 0;
|
762 |
+
|
763 |
+
/**
|
764 |
+
* @var int
|
765 |
+
*/
|
766 |
public $width;
|
767 |
+
|
768 |
+
/**
|
769 |
+
* @var int
|
770 |
+
*/
|
771 |
public $height;
|
772 |
|
773 |
+
/**
|
774 |
+
* @param string $sps
|
775 |
+
*/
|
776 |
public function __construct($sps) {
|
777 |
$this->sps = $sps;
|
778 |
}
|
829 |
}
|
830 |
}
|
831 |
|
832 |
+
/**
|
833 |
+
* @param int $bits
|
834 |
+
*/
|
835 |
public function skipBits($bits) {
|
836 |
$newBits = $this->currentBits + $bits;
|
837 |
$this->currentBytes += (int)floor($newBits / 8);
|
838 |
$this->currentBits = $newBits % 8;
|
839 |
}
|
840 |
|
841 |
+
/**
|
842 |
+
* @return int
|
843 |
+
*/
|
844 |
public function getBit() {
|
845 |
$result = (getid3_lib::BigEndian2Int(substr($this->sps, $this->currentBytes, 1)) >> (7 - $this->currentBits)) & 0x01;
|
846 |
$this->skipBits(1);
|
847 |
return $result;
|
848 |
}
|
849 |
|
850 |
+
/**
|
851 |
+
* @param int $bits
|
852 |
+
*
|
853 |
+
* @return int
|
854 |
+
*/
|
855 |
public function getBits($bits) {
|
856 |
$result = 0;
|
857 |
for ($i = 0; $i < $bits; $i++) {
|
860 |
return $result;
|
861 |
}
|
862 |
|
863 |
+
/**
|
864 |
+
* @return int
|
865 |
+
*/
|
866 |
public function expGolombUe() {
|
867 |
$significantBits = 0;
|
868 |
$bit = $this->getBit();
|
878 |
return (1 << $significantBits) + $this->getBits($significantBits) - 1;
|
879 |
}
|
880 |
|
881 |
+
/**
|
882 |
+
* @return int
|
883 |
+
*/
|
884 |
public function expGolombSe() {
|
885 |
$result = $this->expGolombUe();
|
886 |
if (($result & 0x01) == 0) {
|
890 |
}
|
891 |
}
|
892 |
|
893 |
+
/**
|
894 |
+
* @return int
|
895 |
+
*/
|
896 |
public function getWidth() {
|
897 |
return $this->width;
|
898 |
}
|
899 |
|
900 |
+
/**
|
901 |
+
* @return int
|
902 |
+
*/
|
903 |
public function getHeight() {
|
904 |
return $this->height;
|
905 |
}
|
lib/getid3/module.audio-video.matroska.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio-video.matriska.php //
|
@@ -72,7 +72,7 @@ define('EBML_ID_FILEREFERRAL', 0x0675); // [46][75] --
|
|
72 |
define('EBML_ID_FILEDESCRIPTION', 0x067E); // [46][7E] -- A human-friendly name for the attached file.
|
73 |
define('EBML_ID_FILEUID', 0x06AE); // [46][AE] -- Unique ID representing the file, as random as possible.
|
74 |
define('EBML_ID_CONTENTENCALGO', 0x07E1); // [47][E1] -- The encryption algorithm used. The value '0' means that the contents have not been encrypted but only signed. Predefined values:
|
75 |
-
define('EBML_ID_CONTENTENCKEYID', 0x07E2); // [47][E2] -- For public key algorithms this is the ID of the public key the
|
76 |
define('EBML_ID_CONTENTSIGNATURE', 0x07E3); // [47][E3] -- A cryptographic signature of the contents.
|
77 |
define('EBML_ID_CONTENTSIGKEYID', 0x07E4); // [47][E4] -- This is the ID of the private key the data was signed with.
|
78 |
define('EBML_ID_CONTENTSIGALGO', 0x07E5); // [47][E5] -- The algorithm used for the signature. A value of '0' means that the contents have not been signed but only encrypted. Predefined values:
|
@@ -215,17 +215,33 @@ define('EBML_ID_CLUSTERREFERENCEVIRTUAL', 0x7D); // [FD] --
|
|
215 |
*/
|
216 |
class getid3_matroska extends getid3_handler
|
217 |
{
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
223 |
private $EBMLbuffer = '';
|
224 |
private $EBMLbuffer_offset = 0;
|
225 |
private $EBMLbuffer_length = 0;
|
226 |
private $current_offset = 0;
|
227 |
private $unuseful_elements = array(EBML_ID_CRC32, EBML_ID_VOID);
|
228 |
|
|
|
|
|
|
|
229 |
public function Analyze()
|
230 |
{
|
231 |
$info = &$this->getid3->info;
|
@@ -234,7 +250,7 @@ class getid3_matroska extends getid3_handler
|
|
234 |
try {
|
235 |
$this->parseEBML($info);
|
236 |
} catch (Exception $e) {
|
237 |
-
$
|
238 |
}
|
239 |
|
240 |
// calculate playtime
|
@@ -330,11 +346,13 @@ class getid3_matroska extends getid3_handler
|
|
330 |
break;
|
331 |
|
332 |
case 'A_AC3':
|
|
|
333 |
case 'A_DTS':
|
334 |
case 'A_MPEG/L3':
|
335 |
case 'A_MPEG/L2':
|
336 |
case 'A_FLAC':
|
337 |
-
|
|
|
338 |
|
339 |
if (!isset($info['matroska']['track_data_offsets'][$trackarray['TrackNumber']])) {
|
340 |
$this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because $info[matroska][track_data_offsets]['.$trackarray['TrackNumber'].'] not set');
|
@@ -352,7 +370,7 @@ class getid3_matroska extends getid3_handler
|
|
352 |
}
|
353 |
|
354 |
// analyze
|
355 |
-
$class = 'getid3_'
|
356 |
$header_data_key = $track_info['dataformat'][0] == 'm' ? 'mpeg' : $track_info['dataformat'];
|
357 |
$getid3_audio = new $class($getid3_temp, __CLASS__);
|
358 |
if ($track_info['dataformat'] == 'flac') {
|
@@ -364,8 +382,8 @@ class getid3_matroska extends getid3_handler
|
|
364 |
if (!empty($getid3_temp->info[$header_data_key])) {
|
365 |
$info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info[$header_data_key];
|
366 |
if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
|
367 |
-
foreach ($getid3_temp->info['audio'] as $
|
368 |
-
$track_info[$
|
369 |
}
|
370 |
}
|
371 |
}
|
@@ -419,8 +437,8 @@ class getid3_matroska extends getid3_handler
|
|
419 |
if (!empty($getid3_temp->info['ogg'])) {
|
420 |
$info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info['ogg'];
|
421 |
if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
|
422 |
-
foreach ($getid3_temp->info['audio'] as $
|
423 |
-
$track_info[$
|
424 |
}
|
425 |
}
|
426 |
}
|
@@ -447,9 +465,9 @@ class getid3_matroska extends getid3_handler
|
|
447 |
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
|
448 |
|
449 |
$parsed = getid3_riff::parseWAVEFORMATex($trackarray['CodecPrivate']);
|
450 |
-
foreach ($parsed as $
|
451 |
-
if ($
|
452 |
-
$track_info[$
|
453 |
}
|
454 |
}
|
455 |
$info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $parsed;
|
@@ -494,6 +512,9 @@ class getid3_matroska extends getid3_handler
|
|
494 |
return true;
|
495 |
}
|
496 |
|
|
|
|
|
|
|
497 |
private function parseEBML(&$info) {
|
498 |
// http://www.matroska.org/technical/specs/index.html#EBMLBasics
|
499 |
$this->current_offset = $info['avdataoffset'];
|
@@ -566,8 +587,11 @@ class getid3_matroska extends getid3_handler
|
|
566 |
$this->unhandledElement('seekhead.seek', __LINE__, $sub_seek_entry); }
|
567 |
break;
|
568 |
}
|
569 |
-
|
570 |
-
|
|
|
|
|
|
|
571 |
$info['matroska']['seek'][] = $seek_entry;
|
572 |
}
|
573 |
break;
|
@@ -1223,6 +1247,11 @@ class getid3_matroska extends getid3_handler
|
|
1223 |
}
|
1224 |
}
|
1225 |
|
|
|
|
|
|
|
|
|
|
|
1226 |
private function EnsureBufferHasEnoughData($min_data=1024) {
|
1227 |
if (($this->current_offset - $this->EBMLbuffer_offset) >= ($this->EBMLbuffer_length - $min_data)) {
|
1228 |
$read_bytes = max($min_data, $this->getid3->fread_buffer_size());
|
@@ -1244,6 +1273,9 @@ class getid3_matroska extends getid3_handler
|
|
1244 |
return true;
|
1245 |
}
|
1246 |
|
|
|
|
|
|
|
1247 |
private function readEBMLint() {
|
1248 |
$actual_offset = $this->current_offset - $this->EBMLbuffer_offset;
|
1249 |
|
@@ -1276,6 +1308,12 @@ class getid3_matroska extends getid3_handler
|
|
1276 |
return $int_value;
|
1277 |
}
|
1278 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1279 |
private function readEBMLelementData($length, $check_buffer=false) {
|
1280 |
if ($check_buffer && !$this->EnsureBufferHasEnoughData($length)) {
|
1281 |
return false;
|
@@ -1285,6 +1323,13 @@ class getid3_matroska extends getid3_handler
|
|
1285 |
return $data;
|
1286 |
}
|
1287 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1288 |
private function getEBMLelement(&$element, $parent_end, $get_data=false) {
|
1289 |
if ($this->current_offset >= $parent_end) {
|
1290 |
return false;
|
@@ -1321,6 +1366,11 @@ class getid3_matroska extends getid3_handler
|
|
1321 |
return true;
|
1322 |
}
|
1323 |
|
|
|
|
|
|
|
|
|
|
|
1324 |
private function unhandledElement($type, $line, $element) {
|
1325 |
// warn only about unknown and missed elements, not about unuseful
|
1326 |
if (!in_array($element['id'], $this->unuseful_elements)) {
|
@@ -1333,6 +1383,11 @@ class getid3_matroska extends getid3_handler
|
|
1333 |
}
|
1334 |
}
|
1335 |
|
|
|
|
|
|
|
|
|
|
|
1336 |
private function ExtractCommentsSimpleTag($SimpleTagArray) {
|
1337 |
if (!empty($SimpleTagArray['SimpleTag'])) {
|
1338 |
foreach ($SimpleTagArray['SimpleTag'] as $SimpleTagKey => $SimpleTagData) {
|
@@ -1348,6 +1403,11 @@ class getid3_matroska extends getid3_handler
|
|
1348 |
return true;
|
1349 |
}
|
1350 |
|
|
|
|
|
|
|
|
|
|
|
1351 |
private function HandleEMBLSimpleTag($parent_end) {
|
1352 |
$simpletag_entry = array();
|
1353 |
|
@@ -1378,6 +1438,13 @@ class getid3_matroska extends getid3_handler
|
|
1378 |
return $simpletag_entry;
|
1379 |
}
|
1380 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1381 |
private function HandleEMBLClusterBlock($element, $block_type, &$info) {
|
1382 |
// http://www.matroska.org/technical/specs/index.html#block_structure
|
1383 |
// http://www.matroska.org/technical/specs/index.html#simpleblock_structure
|
@@ -1441,6 +1508,11 @@ class getid3_matroska extends getid3_handler
|
|
1441 |
return $block_data;
|
1442 |
}
|
1443 |
|
|
|
|
|
|
|
|
|
|
|
1444 |
private static function EBML2Int($EBMLstring) {
|
1445 |
// http://matroska.org/specs/
|
1446 |
|
@@ -1483,12 +1555,22 @@ class getid3_matroska extends getid3_handler
|
|
1483 |
return getid3_lib::BigEndian2Int($EBMLstring);
|
1484 |
}
|
1485 |
|
|
|
|
|
|
|
|
|
|
|
1486 |
private static function EBMLdate2unix($EBMLdatestamp) {
|
1487 |
// Date - signed 8 octets integer in nanoseconds with 0 indicating the precise beginning of the millennium (at 2001-01-01T00:00:00,000000000 UTC)
|
1488 |
// 978307200 == mktime(0, 0, 0, 1, 1, 2001) == January 1, 2001 12:00:00am UTC
|
1489 |
return round(($EBMLdatestamp / 1000000000) + 978307200);
|
1490 |
}
|
1491 |
|
|
|
|
|
|
|
|
|
|
|
1492 |
public static function TargetTypeValue($target_type) {
|
1493 |
// http://www.matroska.org/technical/specs/tagging/index.html
|
1494 |
static $TargetTypeValue = array();
|
@@ -1504,6 +1586,11 @@ class getid3_matroska extends getid3_handler
|
|
1504 |
return (isset($TargetTypeValue[$target_type]) ? $TargetTypeValue[$target_type] : $target_type);
|
1505 |
}
|
1506 |
|
|
|
|
|
|
|
|
|
|
|
1507 |
public static function BlockLacingType($lacingtype) {
|
1508 |
// http://matroska.org/technical/specs/index.html#block_structure
|
1509 |
static $BlockLacingType = array();
|
@@ -1516,6 +1603,11 @@ class getid3_matroska extends getid3_handler
|
|
1516 |
return (isset($BlockLacingType[$lacingtype]) ? $BlockLacingType[$lacingtype] : $lacingtype);
|
1517 |
}
|
1518 |
|
|
|
|
|
|
|
|
|
|
|
1519 |
public static function CodecIDtoCommonName($codecid) {
|
1520 |
// http://www.matroska.org/technical/specs/codecid/index.html
|
1521 |
static $CodecIDlist = array();
|
@@ -1523,6 +1615,7 @@ class getid3_matroska extends getid3_handler
|
|
1523 |
$CodecIDlist['A_AAC'] = 'aac';
|
1524 |
$CodecIDlist['A_AAC/MPEG2/LC'] = 'aac';
|
1525 |
$CodecIDlist['A_AC3'] = 'ac3';
|
|
|
1526 |
$CodecIDlist['A_DTS'] = 'dts';
|
1527 |
$CodecIDlist['A_FLAC'] = 'flac';
|
1528 |
$CodecIDlist['A_MPEG/L1'] = 'mp1';
|
@@ -1551,6 +1644,11 @@ class getid3_matroska extends getid3_handler
|
|
1551 |
return (isset($CodecIDlist[$codecid]) ? $CodecIDlist[$codecid] : $codecid);
|
1552 |
}
|
1553 |
|
|
|
|
|
|
|
|
|
|
|
1554 |
private static function EBMLidName($value) {
|
1555 |
static $EBMLidList = array();
|
1556 |
if (empty($EBMLidList)) {
|
@@ -1749,6 +1847,11 @@ class getid3_matroska extends getid3_handler
|
|
1749 |
return (isset($EBMLidList[$value]) ? $EBMLidList[$value] : dechex($value));
|
1750 |
}
|
1751 |
|
|
|
|
|
|
|
|
|
|
|
1752 |
public static function displayUnit($value) {
|
1753 |
// http://www.matroska.org/technical/specs/index.html#DisplayUnit
|
1754 |
static $units = array(
|
@@ -1760,8 +1863,14 @@ class getid3_matroska extends getid3_handler
|
|
1760 |
return (isset($units[$value]) ? $units[$value] : 'unknown');
|
1761 |
}
|
1762 |
|
|
|
|
|
|
|
|
|
|
|
1763 |
private static function getDefaultStreamInfo($streams)
|
1764 |
{
|
|
|
1765 |
foreach (array_reverse($streams) as $stream) {
|
1766 |
if ($stream['default']) {
|
1767 |
break;
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio-video.matriska.php //
|
72 |
define('EBML_ID_FILEDESCRIPTION', 0x067E); // [46][7E] -- A human-friendly name for the attached file.
|
73 |
define('EBML_ID_FILEUID', 0x06AE); // [46][AE] -- Unique ID representing the file, as random as possible.
|
74 |
define('EBML_ID_CONTENTENCALGO', 0x07E1); // [47][E1] -- The encryption algorithm used. The value '0' means that the contents have not been encrypted but only signed. Predefined values:
|
75 |
+
define('EBML_ID_CONTENTENCKEYID', 0x07E2); // [47][E2] -- For public key algorithms this is the ID of the public key the data was encrypted with.
|
76 |
define('EBML_ID_CONTENTSIGNATURE', 0x07E3); // [47][E3] -- A cryptographic signature of the contents.
|
77 |
define('EBML_ID_CONTENTSIGKEYID', 0x07E4); // [47][E4] -- This is the ID of the private key the data was signed with.
|
78 |
define('EBML_ID_CONTENTSIGALGO', 0x07E5); // [47][E5] -- The algorithm used for the signature. A value of '0' means that the contents have not been signed but only encrypted. Predefined values:
|
215 |
*/
|
216 |
class getid3_matroska extends getid3_handler
|
217 |
{
|
218 |
+
/**
|
219 |
+
* If true, do not return information about CLUSTER chunks, since there's a lot of them
|
220 |
+
* and they're not usually useful [default: TRUE].
|
221 |
+
*
|
222 |
+
* @var bool
|
223 |
+
*/
|
224 |
+
public static $hide_clusters = true;
|
225 |
+
|
226 |
+
/**
|
227 |
+
* True to parse the whole file, not only header [default: FALSE].
|
228 |
+
*
|
229 |
+
* @var bool
|
230 |
+
*/
|
231 |
+
public static $parse_whole_file = false;
|
232 |
+
|
233 |
+
/*
|
234 |
+
* Private parser settings/placeholders.
|
235 |
+
*/
|
236 |
private $EBMLbuffer = '';
|
237 |
private $EBMLbuffer_offset = 0;
|
238 |
private $EBMLbuffer_length = 0;
|
239 |
private $current_offset = 0;
|
240 |
private $unuseful_elements = array(EBML_ID_CRC32, EBML_ID_VOID);
|
241 |
|
242 |
+
/**
|
243 |
+
* @return bool
|
244 |
+
*/
|
245 |
public function Analyze()
|
246 |
{
|
247 |
$info = &$this->getid3->info;
|
250 |
try {
|
251 |
$this->parseEBML($info);
|
252 |
} catch (Exception $e) {
|
253 |
+
$this->error('EBML parser: '.$e->getMessage());
|
254 |
}
|
255 |
|
256 |
// calculate playtime
|
346 |
break;
|
347 |
|
348 |
case 'A_AC3':
|
349 |
+
case 'A_EAC3':
|
350 |
case 'A_DTS':
|
351 |
case 'A_MPEG/L3':
|
352 |
case 'A_MPEG/L2':
|
353 |
case 'A_FLAC':
|
354 |
+
$module_dataformat = ($track_info['dataformat'] == 'mp2' ? 'mp3' : ($track_info['dataformat'] == 'eac3' ? 'ac3' : $track_info['dataformat']));
|
355 |
+
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.'.$module_dataformat.'.php', __FILE__, true);
|
356 |
|
357 |
if (!isset($info['matroska']['track_data_offsets'][$trackarray['TrackNumber']])) {
|
358 |
$this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because $info[matroska][track_data_offsets]['.$trackarray['TrackNumber'].'] not set');
|
370 |
}
|
371 |
|
372 |
// analyze
|
373 |
+
$class = 'getid3_'.$module_dataformat;
|
374 |
$header_data_key = $track_info['dataformat'][0] == 'm' ? 'mpeg' : $track_info['dataformat'];
|
375 |
$getid3_audio = new $class($getid3_temp, __CLASS__);
|
376 |
if ($track_info['dataformat'] == 'flac') {
|
382 |
if (!empty($getid3_temp->info[$header_data_key])) {
|
383 |
$info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info[$header_data_key];
|
384 |
if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
|
385 |
+
foreach ($getid3_temp->info['audio'] as $sub_key => $value) {
|
386 |
+
$track_info[$sub_key] = $value;
|
387 |
}
|
388 |
}
|
389 |
}
|
437 |
if (!empty($getid3_temp->info['ogg'])) {
|
438 |
$info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info['ogg'];
|
439 |
if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
|
440 |
+
foreach ($getid3_temp->info['audio'] as $sub_key => $value) {
|
441 |
+
$track_info[$sub_key] = $value;
|
442 |
}
|
443 |
}
|
444 |
}
|
465 |
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
|
466 |
|
467 |
$parsed = getid3_riff::parseWAVEFORMATex($trackarray['CodecPrivate']);
|
468 |
+
foreach ($parsed as $sub_key => $value) {
|
469 |
+
if ($sub_key != 'raw') {
|
470 |
+
$track_info[$sub_key] = $value;
|
471 |
}
|
472 |
}
|
473 |
$info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $parsed;
|
512 |
return true;
|
513 |
}
|
514 |
|
515 |
+
/**
|
516 |
+
* @param array $info
|
517 |
+
*/
|
518 |
private function parseEBML(&$info) {
|
519 |
// http://www.matroska.org/technical/specs/index.html#EBMLBasics
|
520 |
$this->current_offset = $info['avdataoffset'];
|
587 |
$this->unhandledElement('seekhead.seek', __LINE__, $sub_seek_entry); }
|
588 |
break;
|
589 |
}
|
590 |
+
if (!isset($seek_entry['target_id'])) {
|
591 |
+
$this->warning('seek_entry[target_id] unexpectedly not set at '.$seek_entry['offset']);
|
592 |
+
break;
|
593 |
+
}
|
594 |
+
if (($seek_entry['target_id'] != EBML_ID_CLUSTER) || !self::$hide_clusters) { // collect clusters only if required
|
595 |
$info['matroska']['seek'][] = $seek_entry;
|
596 |
}
|
597 |
break;
|
1247 |
}
|
1248 |
}
|
1249 |
|
1250 |
+
/**
|
1251 |
+
* @param int $min_data
|
1252 |
+
*
|
1253 |
+
* @return bool
|
1254 |
+
*/
|
1255 |
private function EnsureBufferHasEnoughData($min_data=1024) {
|
1256 |
if (($this->current_offset - $this->EBMLbuffer_offset) >= ($this->EBMLbuffer_length - $min_data)) {
|
1257 |
$read_bytes = max($min_data, $this->getid3->fread_buffer_size());
|
1273 |
return true;
|
1274 |
}
|
1275 |
|
1276 |
+
/**
|
1277 |
+
* @return int|float|false
|
1278 |
+
*/
|
1279 |
private function readEBMLint() {
|
1280 |
$actual_offset = $this->current_offset - $this->EBMLbuffer_offset;
|
1281 |
|
1308 |
return $int_value;
|
1309 |
}
|
1310 |
|
1311 |
+
/**
|
1312 |
+
* @param int $length
|
1313 |
+
* @param bool $check_buffer
|
1314 |
+
*
|
1315 |
+
* @return string|false
|
1316 |
+
*/
|
1317 |
private function readEBMLelementData($length, $check_buffer=false) {
|
1318 |
if ($check_buffer && !$this->EnsureBufferHasEnoughData($length)) {
|
1319 |
return false;
|
1323 |
return $data;
|
1324 |
}
|
1325 |
|
1326 |
+
/**
|
1327 |
+
* @param array $element
|
1328 |
+
* @param int $parent_end
|
1329 |
+
* @param array|bool $get_data
|
1330 |
+
*
|
1331 |
+
* @return bool
|
1332 |
+
*/
|
1333 |
private function getEBMLelement(&$element, $parent_end, $get_data=false) {
|
1334 |
if ($this->current_offset >= $parent_end) {
|
1335 |
return false;
|
1366 |
return true;
|
1367 |
}
|
1368 |
|
1369 |
+
/**
|
1370 |
+
* @param string $type
|
1371 |
+
* @param int $line
|
1372 |
+
* @param array $element
|
1373 |
+
*/
|
1374 |
private function unhandledElement($type, $line, $element) {
|
1375 |
// warn only about unknown and missed elements, not about unuseful
|
1376 |
if (!in_array($element['id'], $this->unuseful_elements)) {
|
1383 |
}
|
1384 |
}
|
1385 |
|
1386 |
+
/**
|
1387 |
+
* @param array $SimpleTagArray
|
1388 |
+
*
|
1389 |
+
* @return bool
|
1390 |
+
*/
|
1391 |
private function ExtractCommentsSimpleTag($SimpleTagArray) {
|
1392 |
if (!empty($SimpleTagArray['SimpleTag'])) {
|
1393 |
foreach ($SimpleTagArray['SimpleTag'] as $SimpleTagKey => $SimpleTagData) {
|
1403 |
return true;
|
1404 |
}
|
1405 |
|
1406 |
+
/**
|
1407 |
+
* @param int $parent_end
|
1408 |
+
*
|
1409 |
+
* @return array
|
1410 |
+
*/
|
1411 |
private function HandleEMBLSimpleTag($parent_end) {
|
1412 |
$simpletag_entry = array();
|
1413 |
|
1438 |
return $simpletag_entry;
|
1439 |
}
|
1440 |
|
1441 |
+
/**
|
1442 |
+
* @param array $element
|
1443 |
+
* @param int $block_type
|
1444 |
+
* @param array $info
|
1445 |
+
*
|
1446 |
+
* @return array
|
1447 |
+
*/
|
1448 |
private function HandleEMBLClusterBlock($element, $block_type, &$info) {
|
1449 |
// http://www.matroska.org/technical/specs/index.html#block_structure
|
1450 |
// http://www.matroska.org/technical/specs/index.html#simpleblock_structure
|
1508 |
return $block_data;
|
1509 |
}
|
1510 |
|
1511 |
+
/**
|
1512 |
+
* @param string $EBMLstring
|
1513 |
+
*
|
1514 |
+
* @return int|float|false
|
1515 |
+
*/
|
1516 |
private static function EBML2Int($EBMLstring) {
|
1517 |
// http://matroska.org/specs/
|
1518 |
|
1555 |
return getid3_lib::BigEndian2Int($EBMLstring);
|
1556 |
}
|
1557 |
|
1558 |
+
/**
|
1559 |
+
* @param int $EBMLdatestamp
|
1560 |
+
*
|
1561 |
+
* @return float
|
1562 |
+
*/
|
1563 |
private static function EBMLdate2unix($EBMLdatestamp) {
|
1564 |
// Date - signed 8 octets integer in nanoseconds with 0 indicating the precise beginning of the millennium (at 2001-01-01T00:00:00,000000000 UTC)
|
1565 |
// 978307200 == mktime(0, 0, 0, 1, 1, 2001) == January 1, 2001 12:00:00am UTC
|
1566 |
return round(($EBMLdatestamp / 1000000000) + 978307200);
|
1567 |
}
|
1568 |
|
1569 |
+
/**
|
1570 |
+
* @param int $target_type
|
1571 |
+
*
|
1572 |
+
* @return string|int
|
1573 |
+
*/
|
1574 |
public static function TargetTypeValue($target_type) {
|
1575 |
// http://www.matroska.org/technical/specs/tagging/index.html
|
1576 |
static $TargetTypeValue = array();
|
1586 |
return (isset($TargetTypeValue[$target_type]) ? $TargetTypeValue[$target_type] : $target_type);
|
1587 |
}
|
1588 |
|
1589 |
+
/**
|
1590 |
+
* @param int $lacingtype
|
1591 |
+
*
|
1592 |
+
* @return string|int
|
1593 |
+
*/
|
1594 |
public static function BlockLacingType($lacingtype) {
|
1595 |
// http://matroska.org/technical/specs/index.html#block_structure
|
1596 |
static $BlockLacingType = array();
|
1603 |
return (isset($BlockLacingType[$lacingtype]) ? $BlockLacingType[$lacingtype] : $lacingtype);
|
1604 |
}
|
1605 |
|
1606 |
+
/**
|
1607 |
+
* @param string $codecid
|
1608 |
+
*
|
1609 |
+
* @return string
|
1610 |
+
*/
|
1611 |
public static function CodecIDtoCommonName($codecid) {
|
1612 |
// http://www.matroska.org/technical/specs/codecid/index.html
|
1613 |
static $CodecIDlist = array();
|
1615 |
$CodecIDlist['A_AAC'] = 'aac';
|
1616 |
$CodecIDlist['A_AAC/MPEG2/LC'] = 'aac';
|
1617 |
$CodecIDlist['A_AC3'] = 'ac3';
|
1618 |
+
$CodecIDlist['A_EAC3'] = 'eac3';
|
1619 |
$CodecIDlist['A_DTS'] = 'dts';
|
1620 |
$CodecIDlist['A_FLAC'] = 'flac';
|
1621 |
$CodecIDlist['A_MPEG/L1'] = 'mp1';
|
1644 |
return (isset($CodecIDlist[$codecid]) ? $CodecIDlist[$codecid] : $codecid);
|
1645 |
}
|
1646 |
|
1647 |
+
/**
|
1648 |
+
* @param int $value
|
1649 |
+
*
|
1650 |
+
* @return string
|
1651 |
+
*/
|
1652 |
private static function EBMLidName($value) {
|
1653 |
static $EBMLidList = array();
|
1654 |
if (empty($EBMLidList)) {
|
1847 |
return (isset($EBMLidList[$value]) ? $EBMLidList[$value] : dechex($value));
|
1848 |
}
|
1849 |
|
1850 |
+
/**
|
1851 |
+
* @param int $value
|
1852 |
+
*
|
1853 |
+
* @return string
|
1854 |
+
*/
|
1855 |
public static function displayUnit($value) {
|
1856 |
// http://www.matroska.org/technical/specs/index.html#DisplayUnit
|
1857 |
static $units = array(
|
1863 |
return (isset($units[$value]) ? $units[$value] : 'unknown');
|
1864 |
}
|
1865 |
|
1866 |
+
/**
|
1867 |
+
* @param array $streams
|
1868 |
+
*
|
1869 |
+
* @return array
|
1870 |
+
*/
|
1871 |
private static function getDefaultStreamInfo($streams)
|
1872 |
{
|
1873 |
+
$stream = array();
|
1874 |
foreach (array_reverse($streams) as $stream) {
|
1875 |
if ($stream['default']) {
|
1876 |
break;
|
lib/getid3/module.audio-video.mpeg.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio-video.mpeg.php //
|
@@ -16,7 +16,8 @@
|
|
16 |
|
17 |
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true);
|
18 |
|
19 |
-
class getid3_mpeg extends getid3_handler
|
|
|
20 |
|
21 |
const START_CODE_BASE = "\x00\x00\x01";
|
22 |
const VIDEO_PICTURE_START = "\x00\x00\x01\x00";
|
@@ -28,7 +29,9 @@ class getid3_mpeg extends getid3_handler {
|
|
28 |
const VIDEO_GROUP_START = "\x00\x00\x01\xB8";
|
29 |
const AUDIO_START = "\x00\x00\x01\xC0";
|
30 |
|
31 |
-
|
|
|
|
|
32 |
public function Analyze() {
|
33 |
$info = &$this->getid3->info;
|
34 |
|
@@ -87,11 +90,9 @@ class getid3_mpeg extends getid3_handler {
|
|
87 |
break;
|
88 |
|
89 |
case 0xB3: // sequence_header_code
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
Also the MPEG stream is designed as a bitstream and often doesn't align nicely with byte boundaries.
|
94 |
-
*/
|
95 |
$info['video']['codec'] = 'MPEG-1'; // will be updated if extension_start_code found
|
96 |
|
97 |
$bitstream = getid3_lib::BigEndian2Bin(substr($MPEGstreamData, $StartCodeOffset + 4, 8));
|
@@ -122,8 +123,8 @@ class getid3_mpeg extends getid3_handler {
|
|
122 |
}
|
123 |
}
|
124 |
|
125 |
-
$info['mpeg']['video']['pixel_aspect_ratio'] = self::videoAspectRatioLookup($info['mpeg']['video']['raw']['aspect_ratio_information']);
|
126 |
-
$info['mpeg']['video']['pixel_aspect_ratio_text'] = self::videoAspectRatioTextLookup($info['mpeg']['video']['raw']['aspect_ratio_information']);
|
127 |
$info['mpeg']['video']['frame_rate'] = self::videoFramerateLookup($info['mpeg']['video']['raw']['frame_rate_code']);
|
128 |
if ($info['mpeg']['video']['raw']['bitrate'] == 0x3FFFF) { // 18 set bits = VBR
|
129 |
//$this->warning('This version of getID3() ['.$this->getid3->version().'] cannot determine average bitrate of VBR MPEG video files');
|
@@ -169,6 +170,16 @@ class getid3_mpeg extends getid3_handler {
|
|
169 |
$info['video']['interlaced'] = !$info['mpeg']['video']['raw']['progressive_sequence'];
|
170 |
$info['mpeg']['video']['interlaced'] = !$info['mpeg']['video']['raw']['progressive_sequence'];
|
171 |
$info['mpeg']['video']['chroma_format'] = self::chromaFormatTextLookup($info['mpeg']['video']['raw']['chroma_format']);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
172 |
break;
|
173 |
|
174 |
case 2: // 0010 Sequence Display Extension ID
|
@@ -258,7 +269,7 @@ class getid3_mpeg extends getid3_handler {
|
|
258 |
|
259 |
case 0xB8: // group_of_pictures_header
|
260 |
$GOPcounter++;
|
261 |
-
if ($info['mpeg']['video']['bitrate_mode'] == 'vbr') {
|
262 |
$bitstream = getid3_lib::BigEndian2Bin(substr($MPEGstreamData, $StartCodeOffset + 4, 4)); // 27 bits needed for group_of_pictures_header
|
263 |
$bitstreamoffset = 0;
|
264 |
|
@@ -274,7 +285,7 @@ class getid3_mpeg extends getid3_handler {
|
|
274 |
$GOPheader['closed_gop'] = self::readBitsFromStream($bitstream, $bitstreamoffset, 1); // 1 bit flag: closed_gop
|
275 |
$GOPheader['broken_link'] = self::readBitsFromStream($bitstream, $bitstreamoffset, 1); // 1 bit flag: broken_link
|
276 |
|
277 |
-
$time_code_separator = ($GOPheader['drop_frame_flag'] ? ';' : ':'); // While non-drop time code is displayed with colons separating the digit pairs
|
278 |
$GOPheader['time_code'] = sprintf('%02d'.$time_code_separator.'%02d'.$time_code_separator.'%02d'.$time_code_separator.'%02d', $GOPheader['time_code_hours'], $GOPheader['time_code_minutes'], $GOPheader['time_code_seconds'], $GOPheader['time_code_pictures']);
|
279 |
|
280 |
$info['mpeg']['group_of_pictures'][] = $GOPheader;
|
@@ -459,7 +470,7 @@ $PackedElementaryStream['additional_header_bytes'] = $additional_header_bytes;
|
|
459 |
// // break;
|
460 |
// //}
|
461 |
// //$info['playtime_seconds'] *= $multiplier;
|
462 |
-
// //$
|
463 |
// if ($info['video']['bitrate'] < 50000) {
|
464 |
// $this->warning('Interleaved MPEG audio/video playtime may be slightly inaccurate for video bitrates below 100kbps. Except in extreme low-bitrate situations, error should be less than 1%. Report to info@getid3.org if greater than this.');
|
465 |
// }
|
@@ -502,6 +513,14 @@ echo 'average_File_bitrate = '.number_format(array_sum($vbr_bitrates) / count($v
|
|
502 |
return true;
|
503 |
}
|
504 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
505 |
private function readBitsFromStream(&$bitstream, &$bitstreamoffset, $bits_to_read, $return_singlebit_as_boolean=true) {
|
506 |
$return = bindec(substr($bitstream, $bitstreamoffset, $bits_to_read));
|
507 |
$bitstreamoffset += $bits_to_read;
|
@@ -511,7 +530,12 @@ echo 'average_File_bitrate = '.number_format(array_sum($vbr_bitrates) / count($v
|
|
511 |
return $return;
|
512 |
}
|
513 |
|
514 |
-
|
|
|
|
|
|
|
|
|
|
|
515 |
public static function systemNonOverheadPercentage($VideoBitrate, $AudioBitrate) {
|
516 |
$OverheadPercentage = 0;
|
517 |
|
@@ -563,44 +587,93 @@ echo 'average_File_bitrate = '.number_format(array_sum($vbr_bitrates) / count($v
|
|
563 |
return $OverheadPercentage;
|
564 |
}
|
565 |
|
566 |
-
|
|
|
|
|
|
|
|
|
567 |
public static function videoFramerateLookup($rawframerate) {
|
568 |
$lookup = array(0, 23.976, 24, 25, 29.97, 30, 50, 59.94, 60);
|
569 |
-
return (isset($lookup[$rawframerate]) ?
|
570 |
}
|
571 |
|
572 |
-
|
573 |
-
|
574 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
575 |
}
|
576 |
|
577 |
-
|
578 |
-
|
579 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
580 |
}
|
581 |
|
|
|
|
|
|
|
|
|
|
|
582 |
public static function videoFormatTextLookup($video_format) {
|
583 |
// ISO/IEC 13818-2, section 6.3.6, Table 6-6. Meaning of video_format
|
584 |
$lookup = array('component', 'PAL', 'NTSC', 'SECAM', 'MAC', 'Unspecified video format', 'reserved(6)', 'reserved(7)');
|
585 |
return (isset($lookup[$video_format]) ? $lookup[$video_format] : '');
|
586 |
}
|
587 |
|
|
|
|
|
|
|
|
|
|
|
588 |
public static function scalableModeTextLookup($scalable_mode) {
|
589 |
// ISO/IEC 13818-2, section 6.3.8, Table 6-10. Definition of scalable_mode
|
590 |
$lookup = array('data partitioning', 'spatial scalability', 'SNR scalability', 'temporal scalability');
|
591 |
return (isset($lookup[$scalable_mode]) ? $lookup[$scalable_mode] : '');
|
592 |
}
|
593 |
|
|
|
|
|
|
|
|
|
|
|
594 |
public static function pictureStructureTextLookup($picture_structure) {
|
595 |
// ISO/IEC 13818-2, section 6.3.11, Table 6-14 Meaning of picture_structure
|
596 |
$lookup = array('reserved', 'Top Field', 'Bottom Field', 'Frame picture');
|
597 |
return (isset($lookup[$picture_structure]) ? $lookup[$picture_structure] : '');
|
598 |
}
|
599 |
|
|
|
|
|
|
|
|
|
|
|
600 |
public static function chromaFormatTextLookup($chroma_format) {
|
601 |
// ISO/IEC 13818-2, section 6.3.11, Table 6-14 Meaning of picture_structure
|
602 |
$lookup = array('reserved', '4:2:0', '4:2:2', '4:4:4');
|
603 |
return (isset($lookup[$chroma_format]) ? $lookup[$chroma_format] : '');
|
604 |
}
|
605 |
|
606 |
-
}
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio-video.mpeg.php //
|
16 |
|
17 |
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true);
|
18 |
|
19 |
+
class getid3_mpeg extends getid3_handler
|
20 |
+
{
|
21 |
|
22 |
const START_CODE_BASE = "\x00\x00\x01";
|
23 |
const VIDEO_PICTURE_START = "\x00\x00\x01\x00";
|
29 |
const VIDEO_GROUP_START = "\x00\x00\x01\xB8";
|
30 |
const AUDIO_START = "\x00\x00\x01\xC0";
|
31 |
|
32 |
+
/**
|
33 |
+
* @return bool
|
34 |
+
*/
|
35 |
public function Analyze() {
|
36 |
$info = &$this->getid3->info;
|
37 |
|
90 |
break;
|
91 |
|
92 |
case 0xB3: // sequence_header_code
|
93 |
+
// Note: purposely doing the less-pretty (and probably a bit slower) method of using string of bits rather than bitwise operations.
|
94 |
+
// Mostly because PHP 32-bit doesn't handle unsigned integers well for bitwise operation.
|
95 |
+
// Also the MPEG stream is designed as a bitstream and often doesn't align nicely with byte boundaries.
|
|
|
|
|
96 |
$info['video']['codec'] = 'MPEG-1'; // will be updated if extension_start_code found
|
97 |
|
98 |
$bitstream = getid3_lib::BigEndian2Bin(substr($MPEGstreamData, $StartCodeOffset + 4, 8));
|
123 |
}
|
124 |
}
|
125 |
|
126 |
+
$info['mpeg']['video']['pixel_aspect_ratio'] = self::videoAspectRatioLookup($info['mpeg']['video']['raw']['aspect_ratio_information']); // may be overridden later if file turns out to be MPEG-2
|
127 |
+
$info['mpeg']['video']['pixel_aspect_ratio_text'] = self::videoAspectRatioTextLookup($info['mpeg']['video']['raw']['aspect_ratio_information']); // may be overridden later if file turns out to be MPEG-2
|
128 |
$info['mpeg']['video']['frame_rate'] = self::videoFramerateLookup($info['mpeg']['video']['raw']['frame_rate_code']);
|
129 |
if ($info['mpeg']['video']['raw']['bitrate'] == 0x3FFFF) { // 18 set bits = VBR
|
130 |
//$this->warning('This version of getID3() ['.$this->getid3->version().'] cannot determine average bitrate of VBR MPEG video files');
|
170 |
$info['video']['interlaced'] = !$info['mpeg']['video']['raw']['progressive_sequence'];
|
171 |
$info['mpeg']['video']['interlaced'] = !$info['mpeg']['video']['raw']['progressive_sequence'];
|
172 |
$info['mpeg']['video']['chroma_format'] = self::chromaFormatTextLookup($info['mpeg']['video']['raw']['chroma_format']);
|
173 |
+
|
174 |
+
if (isset($info['mpeg']['video']['raw']['aspect_ratio_information'])) {
|
175 |
+
// MPEG-2 defines the aspect ratio flag differently from MPEG-1, but the MPEG-2 extension start code may occur after we've already looked up the aspect ratio assuming it was MPEG-1, so re-lookup assuming MPEG-2
|
176 |
+
// This must be done after the extended size is known, so the display aspect ratios can be converted to pixel aspect ratios.
|
177 |
+
$info['mpeg']['video']['pixel_aspect_ratio'] = self::videoAspectRatioLookup($info['mpeg']['video']['raw']['aspect_ratio_information'], 2, $info['video']['resolution_x'], $info['video']['resolution_y']);
|
178 |
+
$info['mpeg']['video']['pixel_aspect_ratio_text'] = self::videoAspectRatioTextLookup($info['mpeg']['video']['raw']['aspect_ratio_information'], 2);
|
179 |
+
$info['video']['pixel_aspect_ratio'] = $info['mpeg']['video']['pixel_aspect_ratio'];
|
180 |
+
$info['video']['pixel_aspect_ratio_text'] = $info['mpeg']['video']['pixel_aspect_ratio_text'];
|
181 |
+
}
|
182 |
+
|
183 |
break;
|
184 |
|
185 |
case 2: // 0010 Sequence Display Extension ID
|
269 |
|
270 |
case 0xB8: // group_of_pictures_header
|
271 |
$GOPcounter++;
|
272 |
+
if (!empty($info['mpeg']['video']['bitrate_mode']) && ($info['mpeg']['video']['bitrate_mode'] == 'vbr')) {
|
273 |
$bitstream = getid3_lib::BigEndian2Bin(substr($MPEGstreamData, $StartCodeOffset + 4, 4)); // 27 bits needed for group_of_pictures_header
|
274 |
$bitstreamoffset = 0;
|
275 |
|
285 |
$GOPheader['closed_gop'] = self::readBitsFromStream($bitstream, $bitstreamoffset, 1); // 1 bit flag: closed_gop
|
286 |
$GOPheader['broken_link'] = self::readBitsFromStream($bitstream, $bitstreamoffset, 1); // 1 bit flag: broken_link
|
287 |
|
288 |
+
$time_code_separator = ($GOPheader['drop_frame_flag'] ? ';' : ':'); // While non-drop time code is displayed with colons separating the digit pairs "HH:MM:SS:FF" drop frame is usually represented with a semi-colon (;) or period (.) as the divider between all the digit pairs "HH;MM;SS;FF", "HH.MM.SS.FF"
|
289 |
$GOPheader['time_code'] = sprintf('%02d'.$time_code_separator.'%02d'.$time_code_separator.'%02d'.$time_code_separator.'%02d', $GOPheader['time_code_hours'], $GOPheader['time_code_minutes'], $GOPheader['time_code_seconds'], $GOPheader['time_code_pictures']);
|
290 |
|
291 |
$info['mpeg']['group_of_pictures'][] = $GOPheader;
|
470 |
// // break;
|
471 |
// //}
|
472 |
// //$info['playtime_seconds'] *= $multiplier;
|
473 |
+
// //$this->warning('Interleaved MPEG audio/video playtime may be inaccurate. With current hack should be within a few seconds of accurate. Report to info@getid3.org if off by more than 10 seconds.');
|
474 |
// if ($info['video']['bitrate'] < 50000) {
|
475 |
// $this->warning('Interleaved MPEG audio/video playtime may be slightly inaccurate for video bitrates below 100kbps. Except in extreme low-bitrate situations, error should be less than 1%. Report to info@getid3.org if greater than this.');
|
476 |
// }
|
513 |
return true;
|
514 |
}
|
515 |
|
516 |
+
/**
|
517 |
+
* @param string $bitstream
|
518 |
+
* @param int $bitstreamoffset
|
519 |
+
* @param int $bits_to_read
|
520 |
+
* @param bool $return_singlebit_as_boolean
|
521 |
+
*
|
522 |
+
* @return bool|float|int
|
523 |
+
*/
|
524 |
private function readBitsFromStream(&$bitstream, &$bitstreamoffset, $bits_to_read, $return_singlebit_as_boolean=true) {
|
525 |
$return = bindec(substr($bitstream, $bitstreamoffset, $bits_to_read));
|
526 |
$bitstreamoffset += $bits_to_read;
|
530 |
return $return;
|
531 |
}
|
532 |
|
533 |
+
/**
|
534 |
+
* @param int $VideoBitrate
|
535 |
+
* @param int $AudioBitrate
|
536 |
+
*
|
537 |
+
* @return float|int
|
538 |
+
*/
|
539 |
public static function systemNonOverheadPercentage($VideoBitrate, $AudioBitrate) {
|
540 |
$OverheadPercentage = 0;
|
541 |
|
587 |
return $OverheadPercentage;
|
588 |
}
|
589 |
|
590 |
+
/**
|
591 |
+
* @param int $rawframerate
|
592 |
+
*
|
593 |
+
* @return float
|
594 |
+
*/
|
595 |
public static function videoFramerateLookup($rawframerate) {
|
596 |
$lookup = array(0, 23.976, 24, 25, 29.97, 30, 50, 59.94, 60);
|
597 |
+
return (float) (isset($lookup[$rawframerate]) ? $lookup[$rawframerate] : 0);
|
598 |
}
|
599 |
|
600 |
+
/**
|
601 |
+
* @param int $rawaspectratio
|
602 |
+
* @param int $mpeg_version
|
603 |
+
* @param int $width
|
604 |
+
* @param int $height
|
605 |
+
*
|
606 |
+
* @return float
|
607 |
+
*/
|
608 |
+
public static function videoAspectRatioLookup($rawaspectratio, $mpeg_version=1, $width=0, $height=0) {
|
609 |
+
$lookup = array(
|
610 |
+
1 => array(0, 1, 0.6735, 0.7031, 0.7615, 0.8055, 0.8437, 0.8935, 0.9157, 0.9815, 1.0255, 1.0695, 1.0950, 1.1575, 1.2015, 0),
|
611 |
+
2 => array(0, 1, 1.3333, 1.7778, 2.2100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
612 |
+
);
|
613 |
+
$ratio = (float) (isset($lookup[$mpeg_version][$rawaspectratio]) ? $lookup[$mpeg_version][$rawaspectratio] : 0);
|
614 |
+
if ($mpeg_version == 2 && $ratio != 1) {
|
615 |
+
// Calculate pixel aspect ratio from MPEG-2 display aspect ratio
|
616 |
+
$ratio = $ratio * $height / $width;
|
617 |
+
}
|
618 |
+
return $ratio;
|
619 |
}
|
620 |
|
621 |
+
/**
|
622 |
+
* @param int $rawaspectratio
|
623 |
+
* @param int $mpeg_version
|
624 |
+
*
|
625 |
+
* @return string
|
626 |
+
*/
|
627 |
+
public static function videoAspectRatioTextLookup($rawaspectratio, $mpeg_version=1) {
|
628 |
+
$lookup = array(
|
629 |
+
1 => array('forbidden', 'square pixels', '0.6735', '16:9, 625 line, PAL', '0.7615', '0.8055', '16:9, 525 line, NTSC', '0.8935', '4:3, 625 line, PAL, CCIR601', '0.9815', '1.0255', '1.0695', '4:3, 525 line, NTSC, CCIR601', '1.1575', '1.2015', 'reserved'),
|
630 |
+
2 => array('forbidden', 'square pixels', '4:3', '16:9', '2.21:1', 'reserved', 'reserved', 'reserved', 'reserved', 'reserved', 'reserved', 'reserved', 'reserved', 'reserved', 'reserved', 'reserved'), // http://dvd.sourceforge.net/dvdinfo/mpeghdrs.html
|
631 |
+
);
|
632 |
+
return (isset($lookup[$mpeg_version][$rawaspectratio]) ? $lookup[$mpeg_version][$rawaspectratio] : '');
|
633 |
}
|
634 |
|
635 |
+
/**
|
636 |
+
* @param int $video_format
|
637 |
+
*
|
638 |
+
* @return string
|
639 |
+
*/
|
640 |
public static function videoFormatTextLookup($video_format) {
|
641 |
// ISO/IEC 13818-2, section 6.3.6, Table 6-6. Meaning of video_format
|
642 |
$lookup = array('component', 'PAL', 'NTSC', 'SECAM', 'MAC', 'Unspecified video format', 'reserved(6)', 'reserved(7)');
|
643 |
return (isset($lookup[$video_format]) ? $lookup[$video_format] : '');
|
644 |
}
|
645 |
|
646 |
+
/**
|
647 |
+
* @param int $scalable_mode
|
648 |
+
*
|
649 |
+
* @return string
|
650 |
+
*/
|
651 |
public static function scalableModeTextLookup($scalable_mode) {
|
652 |
// ISO/IEC 13818-2, section 6.3.8, Table 6-10. Definition of scalable_mode
|
653 |
$lookup = array('data partitioning', 'spatial scalability', 'SNR scalability', 'temporal scalability');
|
654 |
return (isset($lookup[$scalable_mode]) ? $lookup[$scalable_mode] : '');
|
655 |
}
|
656 |
|
657 |
+
/**
|
658 |
+
* @param int $picture_structure
|
659 |
+
*
|
660 |
+
* @return string
|
661 |
+
*/
|
662 |
public static function pictureStructureTextLookup($picture_structure) {
|
663 |
// ISO/IEC 13818-2, section 6.3.11, Table 6-14 Meaning of picture_structure
|
664 |
$lookup = array('reserved', 'Top Field', 'Bottom Field', 'Frame picture');
|
665 |
return (isset($lookup[$picture_structure]) ? $lookup[$picture_structure] : '');
|
666 |
}
|
667 |
|
668 |
+
/**
|
669 |
+
* @param int $chroma_format
|
670 |
+
*
|
671 |
+
* @return string
|
672 |
+
*/
|
673 |
public static function chromaFormatTextLookup($chroma_format) {
|
674 |
// ISO/IEC 13818-2, section 6.3.11, Table 6-14 Meaning of picture_structure
|
675 |
$lookup = array('reserved', '4:2:0', '4:2:2', '4:4:4');
|
676 |
return (isset($lookup[$chroma_format]) ? $lookup[$chroma_format] : '');
|
677 |
}
|
678 |
|
679 |
+
}
|
lib/getid3/module.audio-video.nsv.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.nsv.php //
|
@@ -17,7 +17,9 @@
|
|
17 |
|
18 |
class getid3_nsv extends getid3_handler
|
19 |
{
|
20 |
-
|
|
|
|
|
21 |
public function Analyze() {
|
22 |
$info = &$this->getid3->info;
|
23 |
|
@@ -47,18 +49,23 @@ class getid3_nsv extends getid3_handler
|
|
47 |
break;
|
48 |
|
49 |
default:
|
50 |
-
$
|
51 |
return false;
|
52 |
break;
|
53 |
}
|
54 |
|
55 |
if (!isset($info['nsv']['NSVf'])) {
|
56 |
-
$
|
57 |
}
|
58 |
|
59 |
return true;
|
60 |
}
|
61 |
|
|
|
|
|
|
|
|
|
|
|
62 |
public function getNSVsHeaderFilepointer($fileoffset) {
|
63 |
$info = &$this->getid3->info;
|
64 |
$this->fseek($fileoffset);
|
@@ -69,7 +76,7 @@ class getid3_nsv extends getid3_handler
|
|
69 |
$offset += 4;
|
70 |
|
71 |
if ($info['nsv']['NSVs']['identifier'] != 'NSVs') {
|
72 |
-
$
|
73 |
unset($info['nsv']['NSVs']);
|
74 |
return false;
|
75 |
}
|
@@ -132,6 +139,12 @@ class getid3_nsv extends getid3_handler
|
|
132 |
return true;
|
133 |
}
|
134 |
|
|
|
|
|
|
|
|
|
|
|
|
|
135 |
public function getNSVfHeaderFilepointer($fileoffset, $getTOCoffsets=false) {
|
136 |
$info = &$this->getid3->info;
|
137 |
$this->fseek($fileoffset);
|
@@ -142,7 +155,7 @@ class getid3_nsv extends getid3_handler
|
|
142 |
$offset += 4;
|
143 |
|
144 |
if ($info['nsv']['NSVf']['identifier'] != 'NSVf') {
|
145 |
-
$
|
146 |
unset($info['nsv']['NSVf']);
|
147 |
return false;
|
148 |
}
|
@@ -155,7 +168,7 @@ class getid3_nsv extends getid3_handler
|
|
155 |
$offset += 4;
|
156 |
|
157 |
if ($info['nsv']['NSVf']['file_size'] > $info['avdataend']) {
|
158 |
-
$
|
159 |
}
|
160 |
|
161 |
$info['nsv']['NSVf']['playtime_ms'] = getid3_lib::LittleEndian2Int(substr($NSVfheader, $offset, 4));
|
@@ -168,7 +181,7 @@ class getid3_nsv extends getid3_handler
|
|
168 |
$offset += 4;
|
169 |
|
170 |
if ($info['nsv']['NSVf']['playtime_ms'] == 0) {
|
171 |
-
$
|
172 |
return false;
|
173 |
}
|
174 |
|
@@ -205,18 +218,22 @@ class getid3_nsv extends getid3_handler
|
|
205 |
return true;
|
206 |
}
|
207 |
|
208 |
-
|
|
|
|
|
|
|
|
|
209 |
public static function NSVframerateLookup($framerateindex) {
|
210 |
if ($framerateindex <= 127) {
|
211 |
return (float) $framerateindex;
|
212 |
}
|
213 |
static $NSVframerateLookup = array();
|
214 |
if (empty($NSVframerateLookup)) {
|
215 |
-
$NSVframerateLookup[129] =
|
216 |
-
$NSVframerateLookup[131] =
|
217 |
-
$NSVframerateLookup[133] =
|
218 |
-
$NSVframerateLookup[197] =
|
219 |
-
$NSVframerateLookup[199] =
|
220 |
}
|
221 |
return (isset($NSVframerateLookup[$framerateindex]) ? $NSVframerateLookup[$framerateindex] : false);
|
222 |
}
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.nsv.php //
|
17 |
|
18 |
class getid3_nsv extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @return bool
|
22 |
+
*/
|
23 |
public function Analyze() {
|
24 |
$info = &$this->getid3->info;
|
25 |
|
49 |
break;
|
50 |
|
51 |
default:
|
52 |
+
$this->error('Expecting "NSVs" or "NSVf" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($NSVheader).'"');
|
53 |
return false;
|
54 |
break;
|
55 |
}
|
56 |
|
57 |
if (!isset($info['nsv']['NSVf'])) {
|
58 |
+
$this->warning('NSVf header not present - cannot calculate playtime or bitrate');
|
59 |
}
|
60 |
|
61 |
return true;
|
62 |
}
|
63 |
|
64 |
+
/**
|
65 |
+
* @param int $fileoffset
|
66 |
+
*
|
67 |
+
* @return bool
|
68 |
+
*/
|
69 |
public function getNSVsHeaderFilepointer($fileoffset) {
|
70 |
$info = &$this->getid3->info;
|
71 |
$this->fseek($fileoffset);
|
76 |
$offset += 4;
|
77 |
|
78 |
if ($info['nsv']['NSVs']['identifier'] != 'NSVs') {
|
79 |
+
$this->error('expected "NSVs" at offset ('.$fileoffset.'), found "'.$info['nsv']['NSVs']['identifier'].'" instead');
|
80 |
unset($info['nsv']['NSVs']);
|
81 |
return false;
|
82 |
}
|
139 |
return true;
|
140 |
}
|
141 |
|
142 |
+
/**
|
143 |
+
* @param int $fileoffset
|
144 |
+
* @param bool $getTOCoffsets
|
145 |
+
*
|
146 |
+
* @return bool
|
147 |
+
*/
|
148 |
public function getNSVfHeaderFilepointer($fileoffset, $getTOCoffsets=false) {
|
149 |
$info = &$this->getid3->info;
|
150 |
$this->fseek($fileoffset);
|
155 |
$offset += 4;
|
156 |
|
157 |
if ($info['nsv']['NSVf']['identifier'] != 'NSVf') {
|
158 |
+
$this->error('expected "NSVf" at offset ('.$fileoffset.'), found "'.$info['nsv']['NSVf']['identifier'].'" instead');
|
159 |
unset($info['nsv']['NSVf']);
|
160 |
return false;
|
161 |
}
|
168 |
$offset += 4;
|
169 |
|
170 |
if ($info['nsv']['NSVf']['file_size'] > $info['avdataend']) {
|
171 |
+
$this->warning('truncated file - NSVf header indicates '.$info['nsv']['NSVf']['file_size'].' bytes, file actually '.$info['avdataend'].' bytes');
|
172 |
}
|
173 |
|
174 |
$info['nsv']['NSVf']['playtime_ms'] = getid3_lib::LittleEndian2Int(substr($NSVfheader, $offset, 4));
|
181 |
$offset += 4;
|
182 |
|
183 |
if ($info['nsv']['NSVf']['playtime_ms'] == 0) {
|
184 |
+
$this->error('Corrupt NSV file: NSVf.playtime_ms == zero');
|
185 |
return false;
|
186 |
}
|
187 |
|
218 |
return true;
|
219 |
}
|
220 |
|
221 |
+
/**
|
222 |
+
* @param int $framerateindex
|
223 |
+
*
|
224 |
+
* @return float|false
|
225 |
+
*/
|
226 |
public static function NSVframerateLookup($framerateindex) {
|
227 |
if ($framerateindex <= 127) {
|
228 |
return (float) $framerateindex;
|
229 |
}
|
230 |
static $NSVframerateLookup = array();
|
231 |
if (empty($NSVframerateLookup)) {
|
232 |
+
$NSVframerateLookup[129] = 29.970;
|
233 |
+
$NSVframerateLookup[131] = 23.976;
|
234 |
+
$NSVframerateLookup[133] = 14.985;
|
235 |
+
$NSVframerateLookup[197] = 59.940;
|
236 |
+
$NSVframerateLookup[199] = 47.952;
|
237 |
}
|
238 |
return (isset($NSVframerateLookup[$framerateindex]) ? $NSVframerateLookup[$framerateindex] : false);
|
239 |
}
|
lib/getid3/module.audio-video.quicktime.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio-video.quicktime.php //
|
@@ -24,6 +24,9 @@ class getid3_quicktime extends getid3_handler
|
|
24 |
public $ReturnAtomData = true;
|
25 |
public $ParseAllPossibleAtoms = false;
|
26 |
|
|
|
|
|
|
|
27 |
public function Analyze() {
|
28 |
$info = &$this->getid3->info;
|
29 |
|
@@ -35,10 +38,10 @@ class getid3_quicktime extends getid3_handler
|
|
35 |
|
36 |
$offset = 0;
|
37 |
$atomcounter = 0;
|
38 |
-
$atom_data_read_buffer_size = ($info['php_memory_limit'] ? round($info['php_memory_limit'] /
|
39 |
while ($offset < $info['avdataend']) {
|
40 |
if (!getid3_lib::intValueSupported($offset)) {
|
41 |
-
$
|
42 |
break;
|
43 |
}
|
44 |
$this->fseek($offset);
|
@@ -57,7 +60,7 @@ class getid3_quicktime extends getid3_handler
|
|
57 |
$info['quicktime'][$atomname]['offset'] = $offset;
|
58 |
|
59 |
if (($offset + $atomsize) > $info['avdataend']) {
|
60 |
-
$
|
61 |
return false;
|
62 |
}
|
63 |
|
@@ -81,12 +84,90 @@ class getid3_quicktime extends getid3_handler
|
|
81 |
unset($info['avdataend_tmp']);
|
82 |
}
|
83 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
if (!isset($info['bitrate']) && isset($info['playtime_seconds'])) {
|
85 |
$info['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
|
86 |
}
|
87 |
if (isset($info['bitrate']) && !isset($info['audio']['bitrate']) && !isset($info['quicktime']['video'])) {
|
88 |
$info['audio']['bitrate'] = $info['bitrate'];
|
89 |
}
|
|
|
|
|
|
|
90 |
if (!empty($info['playtime_seconds']) && !isset($info['video']['frame_rate']) && !empty($info['quicktime']['stts_framecount'])) {
|
91 |
foreach ($info['quicktime']['stts_framecount'] as $key => $samples_count) {
|
92 |
$samples_per_second = $samples_count / $info['playtime_seconds'];
|
@@ -98,10 +179,14 @@ class getid3_quicktime extends getid3_handler
|
|
98 |
}
|
99 |
}
|
100 |
}
|
101 |
-
if (
|
102 |
$info['fileformat'] = 'mp4';
|
103 |
-
$info['
|
104 |
-
|
|
|
|
|
|
|
|
|
105 |
}
|
106 |
|
107 |
if (!$this->ReturnAtomData) {
|
@@ -114,1344 +199,1667 @@ class getid3_quicktime extends getid3_handler
|
|
114 |
if (empty($info['video']['dataformat']) && !empty($info['quicktime']['video'])) {
|
115 |
$info['video']['dataformat'] = 'quicktime';
|
116 |
}
|
|
|
|
|
|
|
117 |
|
118 |
return true;
|
119 |
}
|
120 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
public function QuicktimeParseAtom($atomname, $atomsize, $atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) {
|
122 |
// http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm
|
123 |
// https://code.google.com/p/mp4v2/wiki/iTunesMetadata
|
124 |
|
125 |
$info = &$this->getid3->info;
|
126 |
|
127 |
-
$atom_parent = end($atomHierarchy); // not array_pop($atomHierarchy); see
|
128 |
array_push($atomHierarchy, $atomname);
|
129 |
$atom_structure['hierarchy'] = implode(' ', $atomHierarchy);
|
130 |
$atom_structure['name'] = $atomname;
|
131 |
$atom_structure['size'] = $atomsize;
|
132 |
$atom_structure['offset'] = $baseoffset;
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
150 |
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
foreach ($atom_structure['subatoms'] as $subatomarray) {
|
156 |
-
if (!is_integer($subatomarray['name']) || (count($subatomarray['subatoms']) != 1)) {
|
157 |
-
$allnumericnames = false;
|
158 |
-
break;
|
159 |
-
}
|
160 |
-
}
|
161 |
-
if ($allnumericnames) {
|
162 |
-
$newData = array();
|
163 |
foreach ($atom_structure['subatoms'] as $subatomarray) {
|
164 |
-
|
165 |
-
|
166 |
-
$newData[$subatomarray['name']] = $newData_subatomarray;
|
167 |
break;
|
168 |
}
|
169 |
}
|
170 |
-
$
|
171 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
172 |
}
|
173 |
-
|
174 |
-
break;
|
175 |
-
|
176 |
-
case "\x00\x00\x00\x01":
|
177 |
-
case "\x00\x00\x00\x02":
|
178 |
-
case "\x00\x00\x00\x03":
|
179 |
-
case "\x00\x00\x00\x04":
|
180 |
-
case "\x00\x00\x00\x05":
|
181 |
-
$atomname = getid3_lib::BigEndian2Int($atomname);
|
182 |
-
$atom_structure['name'] = $atomname;
|
183 |
-
$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
|
184 |
-
break;
|
185 |
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
|
|
204 |
}
|
205 |
}
|
206 |
-
}
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
}
|
213 |
}
|
214 |
}
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
break;
|
224 |
-
|
225 |
|
226 |
-
case "\xA9".'alb': // ALBum
|
227 |
-
case "\xA9".'ART': //
|
228 |
-
case "\xA9".'art': // ARTist
|
229 |
-
case "\xA9".'aut': //
|
230 |
-
case "\xA9".'cmt': // CoMmenT
|
231 |
-
case "\xA9".'com': // COMposer
|
232 |
-
case "\xA9".'cpy': //
|
233 |
-
case "\xA9".'day': // content created year
|
234 |
-
case "\xA9".'dir': //
|
235 |
-
case "\xA9".'ed1': //
|
236 |
-
case "\xA9".'ed2': //
|
237 |
-
case "\xA9".'ed3': //
|
238 |
-
case "\xA9".'ed4': //
|
239 |
-
case "\xA9".'ed5': //
|
240 |
-
case "\xA9".'ed6': //
|
241 |
-
case "\xA9".'ed7': //
|
242 |
-
case "\xA9".'ed8': //
|
243 |
-
case "\xA9".'ed9': //
|
244 |
-
case "\xA9".'enc': //
|
245 |
-
case "\xA9".'fmt': //
|
246 |
-
case "\xA9".'gen': // GENre
|
247 |
-
case "\xA9".'grp': // GRouPing
|
248 |
-
case "\xA9".'hst': //
|
249 |
-
case "\xA9".'inf': //
|
250 |
-
case "\xA9".'lyr': // LYRics
|
251 |
-
case "\xA9".'mak': //
|
252 |
-
case "\xA9".'mod': //
|
253 |
-
case "\xA9".'nam': // full NAMe
|
254 |
-
case "\xA9".'ope': //
|
255 |
-
case "\xA9".'PRD': //
|
256 |
-
case "\xA9".'prf': //
|
257 |
-
case "\xA9".'req': //
|
258 |
-
case "\xA9".'src': //
|
259 |
-
case "\xA9".'swr': //
|
260 |
-
case "\xA9".'too': // encoder
|
261 |
-
case "\xA9".'trk': // TRacK
|
262 |
-
case "\xA9".'url': //
|
263 |
-
case "\xA9".'wrn': //
|
264 |
-
case "\xA9".'wrt': // WRiTer
|
265 |
-
case '----': // itunes specific
|
266 |
-
case 'aART': // Album ARTist
|
267 |
-
case 'akID': // iTunes store account type
|
268 |
-
case 'apID': // Purchase Account
|
269 |
-
case 'atID': //
|
270 |
-
case 'catg': // CaTeGory
|
271 |
-
case 'cmID': //
|
272 |
-
case 'cnID': //
|
273 |
-
case 'covr': // COVeR artwork
|
274 |
-
case 'cpil': // ComPILation
|
275 |
-
case 'cprt': // CoPyRighT
|
276 |
-
case 'desc': // DESCription
|
277 |
-
case 'disk': // DISK number
|
278 |
-
case 'egid': // Episode Global ID
|
279 |
-
case 'geID': //
|
280 |
-
case 'gnre': // GeNRE
|
281 |
-
case 'hdvd': // HD ViDeo
|
282 |
-
case 'keyw': // KEYWord
|
283 |
-
case 'ldes': // Long DEScription
|
284 |
-
case 'pcst': // PodCaST
|
285 |
-
case 'pgap': // GAPless Playback
|
286 |
-
case 'plID': //
|
287 |
-
case 'purd': // PURchase Date
|
288 |
-
case 'purl': // Podcast URL
|
289 |
-
case 'rati': //
|
290 |
-
case 'rndu': //
|
291 |
-
case 'rpdu': //
|
292 |
-
case 'rtng': // RaTiNG
|
293 |
-
case 'sfID': // iTunes store country
|
294 |
-
case 'soaa': // SOrt Album Artist
|
295 |
-
case 'soal': // SOrt ALbum
|
296 |
-
case 'soar': // SOrt ARtist
|
297 |
-
case 'soco': // SOrt COmposer
|
298 |
-
case 'sonm': // SOrt NaMe
|
299 |
-
case 'sosn': // SOrt Show Name
|
300 |
-
case 'stik': //
|
301 |
-
case 'tmpo': // TeMPO (BPM)
|
302 |
-
case 'trkn': // TRacK Number
|
303 |
-
case 'tven': // tvEpisodeID
|
304 |
-
case 'tves': // TV EpiSode
|
305 |
-
case 'tvnn': // TV Network Name
|
306 |
-
case 'tvsh': // TV SHow Name
|
307 |
-
case 'tvsn': // TV SeasoN
|
308 |
-
if ($atom_parent == 'udta') {
|
309 |
-
// User data atom handler
|
310 |
-
$atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
|
311 |
-
$atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2));
|
312 |
-
$atom_structure['data'] = substr($atom_data, 4);
|
313 |
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
344 |
}
|
345 |
} else {
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
$
|
353 |
-
$
|
354 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
355 |
}
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
|
|
|
|
|
|
362 |
break;
|
|
|
|
|
363 |
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
case 21: // tmpo/cpil flag
|
370 |
-
switch ($atomname) {
|
371 |
-
case 'cpil':
|
372 |
-
case 'hdvd':
|
373 |
-
case 'pcst':
|
374 |
-
case 'pgap':
|
375 |
-
// 8-bit integer (boolean)
|
376 |
-
$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
|
377 |
-
break;
|
378 |
-
|
379 |
-
case 'tmpo':
|
380 |
-
// 16-bit integer
|
381 |
-
$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 2));
|
382 |
-
break;
|
383 |
-
|
384 |
-
case 'disk':
|
385 |
-
case 'trkn':
|
386 |
-
// binary
|
387 |
-
$num = getid3_lib::BigEndian2Int(substr($boxdata, 10, 2));
|
388 |
-
$num_total = getid3_lib::BigEndian2Int(substr($boxdata, 12, 2));
|
389 |
-
$atom_structure['data'] = empty($num) ? '' : $num;
|
390 |
-
$atom_structure['data'] .= empty($num_total) ? '' : '/'.$num_total;
|
391 |
-
break;
|
392 |
-
|
393 |
-
case 'gnre':
|
394 |
-
// enum
|
395 |
-
$GenreID = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
|
396 |
-
$atom_structure['data'] = getid3_id3v1::LookupGenreName($GenreID - 1);
|
397 |
-
break;
|
398 |
-
|
399 |
-
case 'rtng':
|
400 |
-
// 8-bit integer
|
401 |
-
$atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
|
402 |
-
$atom_structure['data'] = $this->QuicktimeContentRatingLookup($atom_structure[$atomname]);
|
403 |
-
break;
|
404 |
-
|
405 |
-
case 'stik':
|
406 |
-
// 8-bit integer (enum)
|
407 |
-
$atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
|
408 |
-
$atom_structure['data'] = $this->QuicktimeSTIKLookup($atom_structure[$atomname]);
|
409 |
-
break;
|
410 |
-
|
411 |
-
case 'sfID':
|
412 |
-
// 32-bit integer
|
413 |
-
$atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
|
414 |
-
$atom_structure['data'] = $this->QuicktimeStoreFrontCodeLookup($atom_structure[$atomname]);
|
415 |
-
break;
|
416 |
-
|
417 |
-
case 'egid':
|
418 |
-
case 'purl':
|
419 |
-
$atom_structure['data'] = substr($boxdata, 8);
|
420 |
-
break;
|
421 |
-
|
422 |
-
case 'plID':
|
423 |
-
// 64-bit integer
|
424 |
-
$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 8));
|
425 |
-
|
426 |
-
case 'atID':
|
427 |
-
case 'cnID':
|
428 |
-
case 'geID':
|
429 |
-
case 'tves':
|
430 |
-
case 'tvsn':
|
431 |
-
default:
|
432 |
-
// 32-bit integer
|
433 |
-
$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
|
434 |
-
}
|
435 |
-
break;
|
436 |
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
449 |
}
|
450 |
-
|
451 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
452 |
|
453 |
-
|
454 |
-
|
455 |
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
|
|
|
460 |
}
|
461 |
}
|
462 |
}
|
463 |
-
|
464 |
-
|
465 |
-
break;
|
466 |
|
467 |
|
468 |
-
|
469 |
-
|
470 |
|
471 |
-
|
472 |
-
|
473 |
|
474 |
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
|
480 |
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
|
487 |
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
|
495 |
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
|
509 |
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
|
515 |
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
|
542 |
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
|
547 |
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
|
554 |
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
|
564 |
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
|
576 |
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
|
582 |
-
|
583 |
-
|
584 |
|
585 |
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
|
597 |
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
603 |
|
604 |
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
$atom_structure['reserved_2'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x0000
|
610 |
-
$atom_structure['slide_show_flag'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 1));
|
611 |
-
$atom_structure['play_on_open_flag'] = getid3_lib::BigEndian2Int(substr($atom_data, 7, 1));
|
612 |
-
|
613 |
-
$atom_structure['flags']['play_on_open'] = (bool) $atom_structure['play_on_open_flag'];
|
614 |
-
$atom_structure['flags']['slide_show'] = (bool) $atom_structure['slide_show_flag'];
|
615 |
-
|
616 |
-
$ptv_lookup[0] = 'normal';
|
617 |
-
$ptv_lookup[1] = 'double';
|
618 |
-
$ptv_lookup[2] = 'half';
|
619 |
-
$ptv_lookup[3] = 'full';
|
620 |
-
$ptv_lookup[4] = 'current';
|
621 |
-
if (isset($ptv_lookup[$atom_structure['display_size_raw']])) {
|
622 |
-
$atom_structure['display_size'] = $ptv_lookup[$atom_structure['display_size_raw']];
|
623 |
-
} else {
|
624 |
-
$info['warning'][] = 'unknown "ptv " display constant ('.$atom_structure['display_size_raw'].')';
|
625 |
-
}
|
626 |
-
break;
|
627 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
628 |
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
//
|
704 |
-
//if ((!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['width'])) && (empty($info['video']['resolution_x']) || empty($info['video']['resolution_y']) || (number_format($info['video']['resolution_x'], 6) != number_format(round($info['video']['resolution_x']), 6)) || (number_format($info['video']['resolution_y'], 6) != number_format(round($info['video']['resolution_y']), 6)))) { // ugly check for floating point numbers
|
705 |
-
if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['height'])) {
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
}
|
712 |
-
|
713 |
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
740 |
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
|
809 |
-
|
810 |
|
811 |
-
|
812 |
-
|
813 |
-
|
|
|
|
|
814 |
}
|
815 |
-
|
816 |
-
}
|
817 |
-
break;
|
818 |
|
819 |
|
820 |
-
|
821 |
-
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
|
828 |
-
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
|
837 |
-
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
846 |
// }
|
|
|
|
|
847 |
//}
|
848 |
-
//
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
853 |
-
|
854 |
-
//foreach ($FrameRateCalculatorArray as $frames_per_second => $frame_count) {
|
855 |
-
// if (($frames_per_second > 60) || ($frames_per_second < 1)) {
|
856 |
-
// // not video FPS information, probably audio information
|
857 |
-
// $sttsFramesTotal = 0;
|
858 |
-
// $sttsSecondsTotal = 0;
|
859 |
-
// break;
|
860 |
-
// }
|
861 |
-
// $sttsFramesTotal += $frame_count;
|
862 |
-
// $sttsSecondsTotal += $frame_count / $frames_per_second;
|
863 |
-
//}
|
864 |
-
//if (($sttsFramesTotal > 0) && ($sttsSecondsTotal > 0)) {
|
865 |
-
// if (($sttsFramesTotal / $sttsSecondsTotal) > $info['video']['frame_rate']) {
|
866 |
-
// $info['video']['frame_rate'] = $sttsFramesTotal / $sttsSecondsTotal;
|
867 |
-
// }
|
868 |
-
//}
|
869 |
-
break;
|
870 |
|
871 |
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
877 |
-
|
878 |
-
|
879 |
-
|
880 |
-
|
|
|
881 |
}
|
882 |
-
|
883 |
-
break;
|
884 |
|
885 |
|
886 |
-
|
887 |
-
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
-
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
-
|
|
|
899 |
}
|
900 |
-
|
901 |
-
break;
|
902 |
|
903 |
|
904 |
-
|
905 |
-
|
906 |
-
|
907 |
-
|
908 |
-
|
909 |
-
|
910 |
-
|
911 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
912 |
for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
|
913 |
-
$atom_structure['
|
914 |
-
$
|
915 |
}
|
916 |
}
|
917 |
-
|
918 |
-
break;
|
919 |
|
920 |
|
921 |
-
|
922 |
-
|
923 |
-
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
-
|
928 |
-
|
929 |
-
|
|
|
930 |
}
|
931 |
-
|
932 |
-
break;
|
933 |
|
934 |
|
935 |
-
|
936 |
-
if ($ParseAllPossibleAtoms) {
|
937 |
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
938 |
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
939 |
$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
|
940 |
-
$
|
941 |
for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
|
942 |
-
$atom_structure['
|
943 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
944 |
}
|
945 |
-
|
946 |
-
break;
|
947 |
|
948 |
|
949 |
-
|
950 |
-
|
951 |
-
|
952 |
-
|
953 |
-
|
954 |
-
|
955 |
-
$atom_structure['
|
956 |
-
$
|
957 |
-
$atom_structure['
|
958 |
-
|
959 |
-
$atom_structure['data_references'][$i]['version'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 1));
|
960 |
-
$drefDataOffset += 1;
|
961 |
-
$atom_structure['data_references'][$i]['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 3)); // hardcoded: 0x0000
|
962 |
-
$drefDataOffset += 3;
|
963 |
-
$atom_structure['data_references'][$i]['data'] = substr($atom_data, $drefDataOffset, ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3));
|
964 |
-
$drefDataOffset += ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3);
|
965 |
-
|
966 |
-
$atom_structure['data_references'][$i]['flags']['self_reference'] = (bool) ($atom_structure['data_references'][$i]['flags_raw'] & 0x001);
|
967 |
-
}
|
968 |
-
break;
|
969 |
|
970 |
|
971 |
-
|
972 |
-
|
973 |
-
|
974 |
-
|
975 |
-
|
976 |
-
|
977 |
-
$atom_structure['opcolor_blue'] = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2));
|
978 |
-
$atom_structure['balance'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 2));
|
979 |
-
$atom_structure['reserved'] = getid3_lib::BigEndian2Int(substr($atom_data, 14, 2));
|
980 |
-
break;
|
981 |
|
982 |
|
983 |
-
|
984 |
-
|
985 |
-
|
986 |
-
|
987 |
-
|
988 |
-
|
|
|
989 |
|
|
|
|
|
990 |
|
991 |
-
case 'vmhd': // Video Media information HeaDer atom
|
992 |
-
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
993 |
-
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
|
994 |
-
$atom_structure['graphics_mode'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2));
|
995 |
-
$atom_structure['opcolor_red'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2));
|
996 |
-
$atom_structure['opcolor_green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 2));
|
997 |
-
$atom_structure['opcolor_blue'] = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2));
|
998 |
|
999 |
-
|
1000 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1001 |
|
|
|
|
|
|
|
|
|
1002 |
|
1003 |
-
case 'hdlr': // HanDLeR reference atom
|
1004 |
-
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1005 |
-
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
1006 |
-
$atom_structure['component_type'] = substr($atom_data, 4, 4);
|
1007 |
-
$atom_structure['component_subtype'] = substr($atom_data, 8, 4);
|
1008 |
-
$atom_structure['component_manufacturer'] = substr($atom_data, 12, 4);
|
1009 |
-
$atom_structure['component_flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
|
1010 |
-
$atom_structure['component_flags_mask'] = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4));
|
1011 |
-
$atom_structure['component_name'] = $this->Pascal2String(substr($atom_data, 24));
|
1012 |
|
1013 |
-
|
1014 |
-
$
|
1015 |
-
|
1016 |
-
|
|
|
|
|
|
|
|
|
|
|
1017 |
|
|
|
|
|
|
|
|
|
|
|
1018 |
|
1019 |
-
|
1020 |
-
|
1021 |
-
|
1022 |
-
|
1023 |
-
|
1024 |
-
|
1025 |
-
|
1026 |
-
|
1027 |
-
$atom_structure['quality'] = getid3_lib::BigEndian2Int(substr($atom_data, 22, 2));
|
1028 |
|
1029 |
-
if ($atom_structure['time_scale'] == 0) {
|
1030 |
-
$info['error'][] = 'Corrupt Quicktime file: mdhd.time_scale == zero';
|
1031 |
-
return false;
|
1032 |
-
}
|
1033 |
-
$info['quicktime']['time_scale'] = (isset($info['quicktime']['time_scale']) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);
|
1034 |
-
|
1035 |
-
$atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
|
1036 |
-
$atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
|
1037 |
-
$atom_structure['playtime_seconds'] = $atom_structure['duration'] / $atom_structure['time_scale'];
|
1038 |
-
$atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']);
|
1039 |
-
if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) {
|
1040 |
-
$info['comments']['language'][] = $atom_structure['language'];
|
1041 |
-
}
|
1042 |
-
break;
|
1043 |
|
|
|
|
|
|
|
|
|
|
|
1044 |
|
1045 |
-
|
1046 |
-
|
1047 |
-
$atom_structure['version_number'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x00
|
1048 |
-
$atom_structure['atom_type'] = substr($atom_data, 6, 4); // usually: 'PICT'
|
1049 |
-
$atom_structure['atom_index'] = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2)); // usually: 0x01
|
1050 |
|
1051 |
-
$atom_structure['modification_date_unix'] = getid3_lib::DateMac2Unix($atom_structure['modification_date']);
|
1052 |
-
break;
|
1053 |
|
|
|
|
|
|
|
|
|
|
|
1054 |
|
1055 |
-
case 'crgn': // Clipping ReGioN atom
|
1056 |
-
$atom_structure['region_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); // The Region size, Region boundary box,
|
1057 |
-
$atom_structure['boundary_box'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 8)); // and Clipping region data fields
|
1058 |
-
$atom_structure['clipping_data'] = substr($atom_data, 10); // constitute a QuickDraw region.
|
1059 |
-
break;
|
1060 |
|
|
|
|
|
|
|
|
|
|
|
1061 |
|
1062 |
-
|
1063 |
-
|
1064 |
-
|
1065 |
-
$atom_structure['preload_flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4));
|
1066 |
-
$atom_structure['default_hints_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
|
1067 |
|
1068 |
-
$atom_structure['default_hints']['double_buffer'] = (bool) ($atom_structure['default_hints_raw'] & 0x0020);
|
1069 |
-
$atom_structure['default_hints']['high_quality'] = (bool) ($atom_structure['default_hints_raw'] & 0x0100);
|
1070 |
-
break;
|
1071 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1072 |
|
1073 |
-
case 'tmcd': // TiMe CoDe atom
|
1074 |
-
case 'chap': // CHAPter list atom
|
1075 |
-
case 'sync': // SYNChronization atom
|
1076 |
-
case 'scpt': // tranSCriPT atom
|
1077 |
-
case 'ssrc': // non-primary SouRCe atom
|
1078 |
-
for ($i = 0; $i < strlen($atom_data); $i += 4) {
|
1079 |
-
@$atom_structure['track_id'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4));
|
1080 |
-
}
|
1081 |
-
break;
|
1082 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1083 |
|
1084 |
-
case 'elst': // Edit LiST atom
|
1085 |
-
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1086 |
-
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
1087 |
-
$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
|
1088 |
-
for ($i = 0; $i < $atom_structure['number_entries']; $i++ ) {
|
1089 |
-
$atom_structure['edit_list'][$i]['track_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 0, 4));
|
1090 |
-
$atom_structure['edit_list'][$i]['media_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 4, 4));
|
1091 |
-
$atom_structure['edit_list'][$i]['media_rate'] = getid3_lib::FixedPoint16_16(substr($atom_data, 8 + ($i * 12) + 8, 4));
|
1092 |
-
}
|
1093 |
-
break;
|
1094 |
|
|
|
|
|
|
|
|
|
|
|
1095 |
|
1096 |
-
case 'kmat': // compressed MATte atom
|
1097 |
-
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1098 |
-
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
1099 |
-
$atom_structure['matte_data_raw'] = substr($atom_data, 4);
|
1100 |
-
break;
|
1101 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1102 |
|
1103 |
-
case 'ctab': // Color TABle atom
|
1104 |
-
$atom_structure['color_table_seed'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); // hardcoded: 0x00000000
|
1105 |
-
$atom_structure['color_table_flags'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x8000
|
1106 |
-
$atom_structure['color_table_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2)) + 1;
|
1107 |
-
for ($colortableentry = 0; $colortableentry < $atom_structure['color_table_size']; $colortableentry++) {
|
1108 |
-
$atom_structure['color_table'][$colortableentry]['alpha'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 0, 2));
|
1109 |
-
$atom_structure['color_table'][$colortableentry]['red'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 2, 2));
|
1110 |
-
$atom_structure['color_table'][$colortableentry]['green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 4, 2));
|
1111 |
-
$atom_structure['color_table'][$colortableentry]['blue'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 6, 2));
|
1112 |
-
}
|
1113 |
-
break;
|
1114 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1115 |
|
1116 |
-
case 'mvhd': // MoVie HeaDer atom
|
1117 |
-
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1118 |
-
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
|
1119 |
-
$atom_structure['creation_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
|
1120 |
-
$atom_structure['modify_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4));
|
1121 |
-
$atom_structure['time_scale'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
|
1122 |
-
$atom_structure['duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
|
1123 |
-
$atom_structure['preferred_rate'] = getid3_lib::FixedPoint16_16(substr($atom_data, 20, 4));
|
1124 |
-
$atom_structure['preferred_volume'] = getid3_lib::FixedPoint8_8(substr($atom_data, 24, 2));
|
1125 |
-
$atom_structure['reserved'] = substr($atom_data, 26, 10);
|
1126 |
-
$atom_structure['matrix_a'] = getid3_lib::FixedPoint16_16(substr($atom_data, 36, 4));
|
1127 |
-
$atom_structure['matrix_b'] = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4));
|
1128 |
-
$atom_structure['matrix_u'] = getid3_lib::FixedPoint2_30(substr($atom_data, 44, 4));
|
1129 |
-
$atom_structure['matrix_c'] = getid3_lib::FixedPoint16_16(substr($atom_data, 48, 4));
|
1130 |
-
$atom_structure['matrix_d'] = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4));
|
1131 |
-
$atom_structure['matrix_v'] = getid3_lib::FixedPoint2_30(substr($atom_data, 56, 4));
|
1132 |
-
$atom_structure['matrix_x'] = getid3_lib::FixedPoint16_16(substr($atom_data, 60, 4));
|
1133 |
-
$atom_structure['matrix_y'] = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4));
|
1134 |
-
$atom_structure['matrix_w'] = getid3_lib::FixedPoint2_30(substr($atom_data, 68, 4));
|
1135 |
-
$atom_structure['preview_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 72, 4));
|
1136 |
-
$atom_structure['preview_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 76, 4));
|
1137 |
-
$atom_structure['poster_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 80, 4));
|
1138 |
-
$atom_structure['selection_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 84, 4));
|
1139 |
-
$atom_structure['selection_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 88, 4));
|
1140 |
-
$atom_structure['current_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 92, 4));
|
1141 |
-
$atom_structure['next_track_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 96, 4));
|
1142 |
-
|
1143 |
-
if ($atom_structure['time_scale'] == 0) {
|
1144 |
-
$info['error'][] = 'Corrupt Quicktime file: mvhd.time_scale == zero';
|
1145 |
-
return false;
|
1146 |
-
}
|
1147 |
-
$atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
|
1148 |
-
$atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
|
1149 |
-
$info['quicktime']['time_scale'] = (isset($info['quicktime']['time_scale']) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);
|
1150 |
-
$info['quicktime']['display_scale'] = $atom_structure['matrix_a'];
|
1151 |
-
$info['playtime_seconds'] = $atom_structure['duration'] / $atom_structure['time_scale'];
|
1152 |
-
break;
|
1153 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1154 |
|
1155 |
-
|
1156 |
-
|
1157 |
-
|
1158 |
-
|
1159 |
-
|
1160 |
-
|
1161 |
-
|
1162 |
-
|
1163 |
-
|
1164 |
-
|
1165 |
-
|
1166 |
-
|
1167 |
-
$atom_structure['reserved3'] = getid3_lib::BigEndian2Int(substr($atom_data, 38, 2));
|
1168 |
-
// http://developer.apple.com/library/mac/#documentation/QuickTime/RM/MovieBasics/MTEditing/K-Chapter/11MatrixFunctions.html
|
1169 |
-
// http://developer.apple.com/library/mac/#documentation/QuickTime/qtff/QTFFChap4/qtff4.html#//apple_ref/doc/uid/TP40000939-CH206-18737
|
1170 |
-
$atom_structure['matrix_a'] = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4));
|
1171 |
-
$atom_structure['matrix_b'] = getid3_lib::FixedPoint16_16(substr($atom_data, 44, 4));
|
1172 |
-
$atom_structure['matrix_u'] = getid3_lib::FixedPoint2_30(substr($atom_data, 48, 4));
|
1173 |
-
$atom_structure['matrix_c'] = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4));
|
1174 |
-
$atom_structure['matrix_d'] = getid3_lib::FixedPoint16_16(substr($atom_data, 56, 4));
|
1175 |
-
$atom_structure['matrix_v'] = getid3_lib::FixedPoint2_30(substr($atom_data, 60, 4));
|
1176 |
-
$atom_structure['matrix_x'] = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4));
|
1177 |
-
$atom_structure['matrix_y'] = getid3_lib::FixedPoint16_16(substr($atom_data, 68, 4));
|
1178 |
-
$atom_structure['matrix_w'] = getid3_lib::FixedPoint2_30(substr($atom_data, 72, 4));
|
1179 |
-
$atom_structure['width'] = getid3_lib::FixedPoint16_16(substr($atom_data, 76, 4));
|
1180 |
-
$atom_structure['height'] = getid3_lib::FixedPoint16_16(substr($atom_data, 80, 4));
|
1181 |
-
$atom_structure['flags']['enabled'] = (bool) ($atom_structure['flags_raw'] & 0x0001);
|
1182 |
-
$atom_structure['flags']['in_movie'] = (bool) ($atom_structure['flags_raw'] & 0x0002);
|
1183 |
-
$atom_structure['flags']['in_preview'] = (bool) ($atom_structure['flags_raw'] & 0x0004);
|
1184 |
-
$atom_structure['flags']['in_poster'] = (bool) ($atom_structure['flags_raw'] & 0x0008);
|
1185 |
-
$atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
|
1186 |
-
$atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
|
1187 |
-
|
1188 |
-
if ($atom_structure['flags']['enabled'] == 1) {
|
1189 |
-
if (!isset($info['video']['resolution_x']) || !isset($info['video']['resolution_y'])) {
|
1190 |
-
$info['video']['resolution_x'] = $atom_structure['width'];
|
1191 |
-
$info['video']['resolution_y'] = $atom_structure['height'];
|
1192 |
}
|
1193 |
-
|
1194 |
-
|
1195 |
-
|
1196 |
-
|
1197 |
-
|
1198 |
-
|
1199 |
-
|
1200 |
-
|
1201 |
-
|
1202 |
-
|
1203 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
1204 |
|
1205 |
|
1206 |
-
|
1207 |
-
|
1208 |
-
|
1209 |
-
|
1210 |
-
|
1211 |
-
|
1212 |
-
|
1213 |
-
|
1214 |
-
|
1215 |
-
$offset += 1;
|
1216 |
-
$atom_structure['length'] = $this->quicktime_read_mp4_descr_length($atom_data, $offset);
|
1217 |
-
//$offset already adjusted by quicktime_read_mp4_descr_length()
|
1218 |
-
$atom_structure['object_descriptor_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2));
|
1219 |
-
$offset += 2;
|
1220 |
-
$atom_structure['od_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
|
1221 |
-
$offset += 1;
|
1222 |
-
$atom_structure['scene_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
|
1223 |
-
$offset += 1;
|
1224 |
-
$atom_structure['audio_profile_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
|
1225 |
-
$offset += 1;
|
1226 |
-
$atom_structure['video_profile_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
|
1227 |
-
$offset += 1;
|
1228 |
-
$atom_structure['graphics_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
|
1229 |
-
$offset += 1;
|
1230 |
-
|
1231 |
-
$atom_structure['num_iods_tracks'] = ($atom_structure['length'] - 7) / 6; // 6 bytes would only be right if all tracks use 1-byte length fields
|
1232 |
-
for ($i = 0; $i < $atom_structure['num_iods_tracks']; $i++) {
|
1233 |
-
$atom_structure['track'][$i]['ES_ID_IncTag'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
|
1234 |
$offset += 1;
|
1235 |
-
$atom_structure['
|
1236 |
//$offset already adjusted by quicktime_read_mp4_descr_length()
|
1237 |
-
$atom_structure['
|
1238 |
-
$offset +=
|
1239 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1240 |
|
1241 |
-
|
1242 |
-
|
1243 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
1244 |
|
1245 |
-
|
1246 |
-
|
1247 |
-
|
1248 |
-
|
1249 |
-
|
|
|
|
|
|
|
|
|
1250 |
|
1251 |
-
|
1252 |
-
|
1253 |
|
1254 |
-
/* due to lack of known documentation, this is a kludge implementation. If you know of documentation on how mdat is properly structed, please send it to info@getid3.org */
|
1255 |
|
1256 |
-
|
1257 |
-
|
1258 |
-
|
1259 |
-
|
1260 |
-
|
1261 |
-
|
1262 |
-
|
1263 |
-
|
1264 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1265 |
}
|
1266 |
-
}
|
1267 |
|
1268 |
-
|
1269 |
-
|
1270 |
-
|
1271 |
-
|
1272 |
-
|
1273 |
-
|
1274 |
-
|
1275 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1276 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1277 |
|
|
|
1278 |
|
1279 |
-
|
|
|
1280 |
|
1281 |
-
|
1282 |
-
|
1283 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1284 |
|
1285 |
-
|
1286 |
-
|
1287 |
-
|
1288 |
-
$
|
1289 |
-
|
1290 |
-
|
1291 |
-
|
1292 |
-
|
1293 |
-
|
1294 |
-
|
1295 |
-
|
1296 |
-
|
1297 |
-
|
1298 |
-
|
1299 |
-
|
1300 |
-
|
1301 |
-
|
1302 |
-
|
1303 |
-
|
1304 |
-
|
1305 |
-
|
1306 |
-
|
1307 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1308 |
}
|
|
|
|
|
1309 |
}
|
1310 |
-
|
1311 |
-
$info['avdataend'] = $OldAVDataEnd;
|
1312 |
-
unset($OldAVDataEnd);
|
1313 |
|
1314 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1315 |
|
1316 |
-
|
1317 |
-
|
|
|
|
|
1318 |
|
1319 |
-
|
1320 |
-
|
1321 |
-
|
1322 |
-
|
1323 |
-
|
1324 |
-
// When writing QuickTime files, it is sometimes necessary to update an atom's size.
|
1325 |
-
// It is impossible to update a 32-bit atom to a 64-bit atom since the 32-bit atom
|
1326 |
-
// is only 8 bytes in size, and the 64-bit atom requires 16 bytes. Therefore, QuickTime
|
1327 |
-
// puts an 8-byte placeholder atom before any atoms it may have to update the size of.
|
1328 |
-
// In this way, if the atom needs to be converted from a 32-bit to a 64-bit atom, the
|
1329 |
-
// placeholder atom can be overwritten to obtain the necessary 8 extra bytes.
|
1330 |
-
// The placeholder atom has a type of kWideAtomPlaceholderType ( 'wide' ).
|
1331 |
-
break;
|
1332 |
|
|
|
|
|
1333 |
|
1334 |
-
|
1335 |
-
|
1336 |
-
|
1337 |
-
|
1338 |
|
1339 |
-
|
1340 |
-
|
1341 |
-
|
1342 |
-
|
1343 |
-
|
1344 |
-
|
1345 |
-
|
1346 |
-
switch ($atom_structure['ctyp']) {
|
1347 |
-
case 'qtvr':
|
1348 |
-
$info['video']['dataformat'] = 'quicktimevr';
|
1349 |
-
break;
|
1350 |
-
}
|
1351 |
-
break;
|
1352 |
|
1353 |
-
|
1354 |
-
|
1355 |
-
|
|
|
1356 |
|
1357 |
-
|
1358 |
-
|
1359 |
-
|
1360 |
-
|
1361 |
-
|
1362 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1363 |
|
1364 |
-
|
1365 |
-
|
1366 |
-
|
1367 |
-
|
1368 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1369 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1370 |
|
1371 |
-
|
1372 |
-
|
1373 |
-
|
1374 |
-
|
1375 |
-
|
1376 |
-
|
1377 |
-
|
1378 |
-
|
1379 |
-
// * http://handbrake.fr/irclogs/handbrake-dev/handbrake-dev20080128_pg2.html
|
1380 |
-
case 'ctts':// STCompositionOffsetAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
|
1381 |
-
case 'cslg':// STCompositionShiftLeastGreatestAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
|
1382 |
-
case 'sdtp':// STSampleDependencyAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
|
1383 |
-
case 'stps':// STPartialSyncSampleAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
|
1384 |
-
//$atom_structure['data'] = $atom_data;
|
1385 |
-
break;
|
1386 |
|
1387 |
-
|
1388 |
-
|
1389 |
-
|
1390 |
-
|
1391 |
-
|
1392 |
-
|
1393 |
-
|
1394 |
-
|
|
|
|
|
|
|
1395 |
}
|
1396 |
-
|
1397 |
-
$info['warning'][] = 'QuickTime atom "©xyz" data does not match expected data pattern at offset '.$baseoffset.'. Please report as getID3() bug.';
|
1398 |
-
}
|
1399 |
-
break;
|
1400 |
|
1401 |
-
|
1402 |
-
|
1403 |
-
|
1404 |
-
|
1405 |
-
|
1406 |
-
|
1407 |
-
|
1408 |
-
|
1409 |
-
|
1410 |
-
$
|
1411 |
-
$
|
1412 |
-
$
|
1413 |
-
|
1414 |
-
}
|
1415 |
-
break;
|
1416 |
-
case 'NCTG': // Nikon - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG
|
1417 |
-
$atom_structure['data'] = $this->QuicktimeParseNikonNCTG($atom_data);
|
1418 |
-
break;
|
1419 |
-
case 'NCHD': // Nikon:MakerNoteVersion - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
|
1420 |
-
case 'NCDB': // Nikon - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
|
1421 |
-
case 'CNCV': // Canon:CompressorVersion - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html
|
1422 |
-
$atom_structure['data'] = $atom_data;
|
1423 |
-
break;
|
1424 |
|
1425 |
-
|
1426 |
-
|
1427 |
-
|
1428 |
-
|
1429 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1430 |
|
1431 |
-
|
1432 |
-
|
1433 |
-
|
1434 |
-
//$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
|
1435 |
-
break;
|
1436 |
|
1437 |
-
|
1438 |
-
|
1439 |
-
|
1440 |
-
$atom_structure['unknown'] = getid3_lib::BigEndian2Int(substr($atom_data, 4 + 2, 2));
|
1441 |
-
$atom_structure['data'] = substr($atom_data, 4 + 4);
|
1442 |
-
break;
|
1443 |
|
1444 |
-
|
1445 |
-
|
1446 |
-
|
1447 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1448 |
}
|
1449 |
array_pop($atomHierarchy);
|
1450 |
return $atom_structure;
|
1451 |
}
|
1452 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1453 |
public function QuicktimeParseContainerAtom($atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) {
|
1454 |
-
//echo 'QuicktimeParseContainerAtom('.substr($atom_data, 4, 4).') @ '.$baseoffset.'<br><br>';
|
1455 |
$atom_structure = false;
|
1456 |
$subatomoffset = 0;
|
1457 |
$subatomcounter = 0;
|
@@ -1466,18 +1874,24 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
|
1466 |
// Furthermore, for historical reasons the list of atoms is optionally
|
1467 |
// terminated by a 32-bit integer set to 0. If you are writing a program
|
1468 |
// to read user data atoms, you should allow for the terminating 0.
|
|
|
|
|
|
|
|
|
1469 |
return $atom_structure;
|
1470 |
}
|
1471 |
-
|
1472 |
-
$atom_structure[$subatomcounter] = $this->QuicktimeParseAtom($subatomname, $subatomsize, $subatomdata, $baseoffset + $subatomoffset, $atomHierarchy, $ParseAllPossibleAtoms);
|
1473 |
-
|
1474 |
$subatomoffset += $subatomsize;
|
1475 |
-
$subatomcounter++;
|
1476 |
}
|
1477 |
return $atom_structure;
|
1478 |
}
|
1479 |
|
1480 |
-
|
|
|
|
|
|
|
|
|
|
|
1481 |
public function quicktime_read_mp4_descr_length($data, &$offset) {
|
1482 |
// http://libquicktime.sourcearchive.com/documentation/2:1.0.2plus-pdebian-2build1/esds_8c-source.html
|
1483 |
$num_bytes = 0;
|
@@ -1489,7 +1903,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
|
1489 |
return $length;
|
1490 |
}
|
1491 |
|
1492 |
-
|
|
|
|
|
|
|
|
|
1493 |
public function QuicktimeLanguageLookup($languageid) {
|
1494 |
// http://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap4/qtff4.html#//apple_ref/doc/uid/TP40000939-CH206-34353
|
1495 |
static $QuicktimeLanguageLookup = array();
|
@@ -1627,6 +2045,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
|
1627 |
return (isset($QuicktimeLanguageLookup[$languageid]) ? $QuicktimeLanguageLookup[$languageid] : 'invalid');
|
1628 |
}
|
1629 |
|
|
|
|
|
|
|
|
|
|
|
1630 |
public function QuicktimeVideoCodecLookup($codecid) {
|
1631 |
static $QuicktimeVideoCodecLookup = array();
|
1632 |
if (empty($QuicktimeVideoCodecLookup)) {
|
@@ -1686,6 +2109,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
|
1686 |
return (isset($QuicktimeVideoCodecLookup[$codecid]) ? $QuicktimeVideoCodecLookup[$codecid] : '');
|
1687 |
}
|
1688 |
|
|
|
|
|
|
|
|
|
|
|
1689 |
public function QuicktimeAudioCodecLookup($codecid) {
|
1690 |
static $QuicktimeAudioCodecLookup = array();
|
1691 |
if (empty($QuicktimeAudioCodecLookup)) {
|
@@ -1731,6 +2159,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
|
1731 |
return (isset($QuicktimeAudioCodecLookup[$codecid]) ? $QuicktimeAudioCodecLookup[$codecid] : '');
|
1732 |
}
|
1733 |
|
|
|
|
|
|
|
|
|
|
|
1734 |
public function QuicktimeDCOMLookup($compressionid) {
|
1735 |
static $QuicktimeDCOMLookup = array();
|
1736 |
if (empty($QuicktimeDCOMLookup)) {
|
@@ -1740,6 +2173,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
|
1740 |
return (isset($QuicktimeDCOMLookup[$compressionid]) ? $QuicktimeDCOMLookup[$compressionid] : '');
|
1741 |
}
|
1742 |
|
|
|
|
|
|
|
|
|
|
|
1743 |
public function QuicktimeColorNameLookup($colordepthid) {
|
1744 |
static $QuicktimeColorNameLookup = array();
|
1745 |
if (empty($QuicktimeColorNameLookup)) {
|
@@ -1758,6 +2196,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
|
1758 |
return (isset($QuicktimeColorNameLookup[$colordepthid]) ? $QuicktimeColorNameLookup[$colordepthid] : 'invalid');
|
1759 |
}
|
1760 |
|
|
|
|
|
|
|
|
|
|
|
1761 |
public function QuicktimeSTIKLookup($stik) {
|
1762 |
static $QuicktimeSTIKLookup = array();
|
1763 |
if (empty($QuicktimeSTIKLookup)) {
|
@@ -1775,66 +2218,75 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
|
1775 |
return (isset($QuicktimeSTIKLookup[$stik]) ? $QuicktimeSTIKLookup[$stik] : 'invalid');
|
1776 |
}
|
1777 |
|
|
|
|
|
|
|
|
|
|
|
1778 |
public function QuicktimeIODSaudioProfileName($audio_profile_id) {
|
1779 |
static $QuicktimeIODSaudioProfileNameLookup = array();
|
1780 |
if (empty($QuicktimeIODSaudioProfileNameLookup)) {
|
1781 |
$QuicktimeIODSaudioProfileNameLookup = array(
|
1782 |
-
|
1783 |
-
|
1784 |
-
|
1785 |
-
|
1786 |
-
|
1787 |
-
|
1788 |
-
|
1789 |
-
|
1790 |
-
|
1791 |
-
|
1792 |
-
|
1793 |
-
|
1794 |
-
|
1795 |
-
|
1796 |
-
|
1797 |
-
|
1798 |
-
|
1799 |
-
|
1800 |
-
|
1801 |
-
|
1802 |
-
|
1803 |
-
|
1804 |
-
|
1805 |
-
|
1806 |
-
|
1807 |
-
|
1808 |
-
|
1809 |
-
|
1810 |
-
|
1811 |
-
|
1812 |
-
|
1813 |
-
|
1814 |
-
|
1815 |
-
|
1816 |
-
|
1817 |
-
|
1818 |
-
|
1819 |
-
|
1820 |
-
|
1821 |
-
|
1822 |
-
|
1823 |
-
|
1824 |
-
|
1825 |
-
|
1826 |
-
|
1827 |
-
|
1828 |
-
|
1829 |
-
|
1830 |
-
|
1831 |
-
|
1832 |
);
|
1833 |
}
|
1834 |
return (isset($QuicktimeIODSaudioProfileNameLookup[$audio_profile_id]) ? $QuicktimeIODSaudioProfileNameLookup[$audio_profile_id] : 'ISO Reserved / User Private');
|
1835 |
}
|
1836 |
|
1837 |
-
|
|
|
|
|
|
|
|
|
1838 |
public function QuicktimeIODSvideoProfileName($video_profile_id) {
|
1839 |
static $QuicktimeIODSvideoProfileNameLookup = array();
|
1840 |
if (empty($QuicktimeIODSvideoProfileNameLookup)) {
|
@@ -1906,7 +2358,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
|
1906 |
return (isset($QuicktimeIODSvideoProfileNameLookup[$video_profile_id]) ? $QuicktimeIODSvideoProfileNameLookup[$video_profile_id] : 'ISO Reserved Profile');
|
1907 |
}
|
1908 |
|
1909 |
-
|
|
|
|
|
|
|
|
|
1910 |
public function QuicktimeContentRatingLookup($rtng) {
|
1911 |
static $QuicktimeContentRatingLookup = array();
|
1912 |
if (empty($QuicktimeContentRatingLookup)) {
|
@@ -1917,6 +2373,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
|
1917 |
return (isset($QuicktimeContentRatingLookup[$rtng]) ? $QuicktimeContentRatingLookup[$rtng] : 'invalid');
|
1918 |
}
|
1919 |
|
|
|
|
|
|
|
|
|
|
|
1920 |
public function QuicktimeStoreAccountTypeLookup($akid) {
|
1921 |
static $QuicktimeStoreAccountTypeLookup = array();
|
1922 |
if (empty($QuicktimeStoreAccountTypeLookup)) {
|
@@ -1926,6 +2387,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
|
1926 |
return (isset($QuicktimeStoreAccountTypeLookup[$akid]) ? $QuicktimeStoreAccountTypeLookup[$akid] : 'invalid');
|
1927 |
}
|
1928 |
|
|
|
|
|
|
|
|
|
|
|
1929 |
public function QuicktimeStoreFrontCodeLookup($sfid) {
|
1930 |
static $QuicktimeStoreFrontCodeLookup = array();
|
1931 |
if (empty($QuicktimeStoreFrontCodeLookup)) {
|
@@ -1955,6 +2421,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
|
1955 |
return (isset($QuicktimeStoreFrontCodeLookup[$sfid]) ? $QuicktimeStoreFrontCodeLookup[$sfid] : 'invalid');
|
1956 |
}
|
1957 |
|
|
|
|
|
|
|
|
|
|
|
1958 |
public function QuicktimeParseNikonNCTG($atom_data) {
|
1959 |
// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG
|
1960 |
// Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from some Nikon cameras such as the Coolpix S8000 and D5100
|
@@ -1997,10 +2468,10 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
|
1997 |
);
|
1998 |
|
1999 |
$offset = 0;
|
|
|
2000 |
$datalength = strlen($atom_data);
|
2001 |
$parsed = array();
|
2002 |
while ($offset < $datalength) {
|
2003 |
-
//echo getid3_lib::PrintHexBytes(substr($atom_data, $offset, 4)).'<br>';
|
2004 |
$record_type = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 4)); $offset += 4;
|
2005 |
$data_size_type = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2)); $offset += 2;
|
2006 |
$data_size = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2)); $offset += 2;
|
@@ -2055,7 +2526,7 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
|
2055 |
$offset += ($data_size * 2);
|
2056 |
break;
|
2057 |
default:
|
2058 |
-
echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br>';
|
2059 |
break 2;
|
2060 |
}
|
2061 |
|
@@ -2133,7 +2604,13 @@ echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br
|
|
2133 |
return $parsed;
|
2134 |
}
|
2135 |
|
2136 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
2137 |
public function CopyToAppropriateCommentsSection($keyname, $data, $boxname='') {
|
2138 |
static $handyatomtranslatorarray = array();
|
2139 |
if (empty($handyatomtranslatorarray)) {
|
@@ -2230,8 +2707,8 @@ echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br
|
|
2230 |
$handyatomtranslatorarray['MusicBrainz Disc Id'] = 'MusicBrainz Disc Id';
|
2231 |
|
2232 |
// http://age.hobba.nl/audio/tag_frame_reference.html
|
2233 |
-
$handyatomtranslatorarray['PLAY_COUNTER'] = 'play_counter'; // Foobar2000 -
|
2234 |
-
$handyatomtranslatorarray['MEDIATYPE'] = 'mediatype'; // Foobar2000 -
|
2235 |
*/
|
2236 |
}
|
2237 |
$info = &$this->getid3->info;
|
@@ -2257,11 +2734,59 @@ echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br
|
|
2257 |
$data = array('data'=>$data, 'image_mime'=>$image_mime);
|
2258 |
}
|
2259 |
}
|
2260 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2261 |
}
|
2262 |
return true;
|
2263 |
}
|
2264 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2265 |
public function NoNullString($nullterminatedstring) {
|
2266 |
// remove the single null terminator on null terminated strings
|
2267 |
if (substr($nullterminatedstring, strlen($nullterminatedstring) - 1, 1) === "\x00") {
|
@@ -2270,9 +2795,111 @@ echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br
|
|
2270 |
return $nullterminatedstring;
|
2271 |
}
|
2272 |
|
|
|
|
|
|
|
|
|
|
|
2273 |
public function Pascal2String($pascalstring) {
|
2274 |
// Pascal strings have 1 unsigned byte at the beginning saying how many chars (1-255) are in the string
|
2275 |
return substr($pascalstring, 1);
|
2276 |
}
|
2277 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2278 |
}
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio-video.quicktime.php //
|
24 |
public $ReturnAtomData = true;
|
25 |
public $ParseAllPossibleAtoms = false;
|
26 |
|
27 |
+
/**
|
28 |
+
* @return bool
|
29 |
+
*/
|
30 |
public function Analyze() {
|
31 |
$info = &$this->getid3->info;
|
32 |
|
38 |
|
39 |
$offset = 0;
|
40 |
$atomcounter = 0;
|
41 |
+
$atom_data_read_buffer_size = max($this->getid3->option_fread_buffer_size * 1024, ($info['php_memory_limit'] ? round($info['php_memory_limit'] / 4) : 1024)); // set read buffer to 25% of PHP memory limit (if one is specified), otherwise use option_fread_buffer_size [default: 32MB]
|
42 |
while ($offset < $info['avdataend']) {
|
43 |
if (!getid3_lib::intValueSupported($offset)) {
|
44 |
+
$this->error('Unable to parse atom at offset '.$offset.' because beyond '.round(PHP_INT_MAX / 1073741824).'GB limit of PHP filesystem functions');
|
45 |
break;
|
46 |
}
|
47 |
$this->fseek($offset);
|
60 |
$info['quicktime'][$atomname]['offset'] = $offset;
|
61 |
|
62 |
if (($offset + $atomsize) > $info['avdataend']) {
|
63 |
+
$this->error('Atom at offset '.$offset.' claims to go beyond end-of-file (length: '.$atomsize.' bytes)');
|
64 |
return false;
|
65 |
}
|
66 |
|
84 |
unset($info['avdataend_tmp']);
|
85 |
}
|
86 |
|
87 |
+
if (!empty($info['quicktime']['comments']['chapters']) && is_array($info['quicktime']['comments']['chapters']) && (count($info['quicktime']['comments']['chapters']) > 0)) {
|
88 |
+
$durations = $this->quicktime_time_to_sample_table($info);
|
89 |
+
for ($i = 0; $i < count($info['quicktime']['comments']['chapters']); $i++) {
|
90 |
+
$bookmark = array();
|
91 |
+
$bookmark['title'] = $info['quicktime']['comments']['chapters'][$i];
|
92 |
+
if (isset($durations[$i])) {
|
93 |
+
$bookmark['duration_sample'] = $durations[$i]['sample_duration'];
|
94 |
+
if ($i > 0) {
|
95 |
+
$bookmark['start_sample'] = $info['quicktime']['bookmarks'][($i - 1)]['start_sample'] + $info['quicktime']['bookmarks'][($i - 1)]['duration_sample'];
|
96 |
+
} else {
|
97 |
+
$bookmark['start_sample'] = 0;
|
98 |
+
}
|
99 |
+
if ($time_scale = $this->quicktime_bookmark_time_scale($info)) {
|
100 |
+
$bookmark['duration_seconds'] = $bookmark['duration_sample'] / $time_scale;
|
101 |
+
$bookmark['start_seconds'] = $bookmark['start_sample'] / $time_scale;
|
102 |
+
}
|
103 |
+
}
|
104 |
+
$info['quicktime']['bookmarks'][] = $bookmark;
|
105 |
+
}
|
106 |
+
}
|
107 |
+
|
108 |
+
if (isset($info['quicktime']['temp_meta_key_names'])) {
|
109 |
+
unset($info['quicktime']['temp_meta_key_names']);
|
110 |
+
}
|
111 |
+
|
112 |
+
if (!empty($info['quicktime']['comments']['location.ISO6709'])) {
|
113 |
+
// https://en.wikipedia.org/wiki/ISO_6709
|
114 |
+
foreach ($info['quicktime']['comments']['location.ISO6709'] as $ISO6709string) {
|
115 |
+
$latitude = false;
|
116 |
+
$longitude = false;
|
117 |
+
$altitude = false;
|
118 |
+
if (preg_match('#^([\\+\\-])([0-9]{2}|[0-9]{4}|[0-9]{6})(\\.[0-9]+)?([\\+\\-])([0-9]{3}|[0-9]{5}|[0-9]{7})(\\.[0-9]+)?(([\\+\\-])([0-9]{3}|[0-9]{5}|[0-9]{7})(\\.[0-9]+)?)?/$#', $ISO6709string, $matches)) {
|
119 |
+
@list($dummy, $lat_sign, $lat_deg, $lat_deg_dec, $lon_sign, $lon_deg, $lon_deg_dec, $dummy, $alt_sign, $alt_deg, $alt_deg_dec) = $matches;
|
120 |
+
|
121 |
+
if (strlen($lat_deg) == 2) { // [+-]DD.D
|
122 |
+
$latitude = floatval(ltrim($lat_deg, '0').$lat_deg_dec);
|
123 |
+
} elseif (strlen($lat_deg) == 4) { // [+-]DDMM.M
|
124 |
+
$latitude = floatval(ltrim(substr($lat_deg, 0, 2), '0')) + floatval(ltrim(substr($lat_deg, 2, 2), '0').$lat_deg_dec / 60);
|
125 |
+
} elseif (strlen($lat_deg) == 6) { // [+-]DDMMSS.S
|
126 |
+
$latitude = floatval(ltrim(substr($lat_deg, 0, 2), '0')) + floatval(ltrim(substr($lat_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($lat_deg, 4, 2), '0').$lat_deg_dec / 3600);
|
127 |
+
}
|
128 |
+
|
129 |
+
if (strlen($lon_deg) == 3) { // [+-]DDD.D
|
130 |
+
$longitude = floatval(ltrim($lon_deg, '0').$lon_deg_dec);
|
131 |
+
} elseif (strlen($lon_deg) == 5) { // [+-]DDDMM.M
|
132 |
+
$longitude = floatval(ltrim(substr($lon_deg, 0, 2), '0')) + floatval(ltrim(substr($lon_deg, 2, 2), '0').$lon_deg_dec / 60);
|
133 |
+
} elseif (strlen($lon_deg) == 7) { // [+-]DDDMMSS.S
|
134 |
+
$longitude = floatval(ltrim(substr($lon_deg, 0, 2), '0')) + floatval(ltrim(substr($lon_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($lon_deg, 4, 2), '0').$lon_deg_dec / 3600);
|
135 |
+
}
|
136 |
+
|
137 |
+
if (strlen($alt_deg) == 3) { // [+-]DDD.D
|
138 |
+
$altitude = floatval(ltrim($alt_deg, '0').$alt_deg_dec);
|
139 |
+
} elseif (strlen($alt_deg) == 5) { // [+-]DDDMM.M
|
140 |
+
$altitude = floatval(ltrim(substr($alt_deg, 0, 2), '0')) + floatval(ltrim(substr($alt_deg, 2, 2), '0').$alt_deg_dec / 60);
|
141 |
+
} elseif (strlen($alt_deg) == 7) { // [+-]DDDMMSS.S
|
142 |
+
$altitude = floatval(ltrim(substr($alt_deg, 0, 2), '0')) + floatval(ltrim(substr($alt_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($alt_deg, 4, 2), '0').$alt_deg_dec / 3600);
|
143 |
+
}
|
144 |
+
|
145 |
+
if ($latitude !== false) {
|
146 |
+
$info['quicktime']['comments']['gps_latitude'][] = (($lat_sign == '-') ? -1 : 1) * floatval($latitude);
|
147 |
+
}
|
148 |
+
if ($longitude !== false) {
|
149 |
+
$info['quicktime']['comments']['gps_longitude'][] = (($lon_sign == '-') ? -1 : 1) * floatval($longitude);
|
150 |
+
}
|
151 |
+
if ($altitude !== false) {
|
152 |
+
$info['quicktime']['comments']['gps_altitude'][] = (($alt_sign == '-') ? -1 : 1) * floatval($altitude);
|
153 |
+
}
|
154 |
+
}
|
155 |
+
if ($latitude === false) {
|
156 |
+
$this->warning('location.ISO6709 string not parsed correctly: "'.$ISO6709string.'", please submit as a bug');
|
157 |
+
}
|
158 |
+
break;
|
159 |
+
}
|
160 |
+
}
|
161 |
+
|
162 |
if (!isset($info['bitrate']) && isset($info['playtime_seconds'])) {
|
163 |
$info['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
|
164 |
}
|
165 |
if (isset($info['bitrate']) && !isset($info['audio']['bitrate']) && !isset($info['quicktime']['video'])) {
|
166 |
$info['audio']['bitrate'] = $info['bitrate'];
|
167 |
}
|
168 |
+
if (!empty($info['bitrate']) && !empty($info['audio']['bitrate']) && empty($info['video']['bitrate']) && !empty($info['video']['frame_rate']) && !empty($info['video']['resolution_x']) && ($info['bitrate'] > $info['audio']['bitrate'])) {
|
169 |
+
$info['video']['bitrate'] = $info['bitrate'] - $info['audio']['bitrate'];
|
170 |
+
}
|
171 |
if (!empty($info['playtime_seconds']) && !isset($info['video']['frame_rate']) && !empty($info['quicktime']['stts_framecount'])) {
|
172 |
foreach ($info['quicktime']['stts_framecount'] as $key => $samples_count) {
|
173 |
$samples_per_second = $samples_count / $info['playtime_seconds'];
|
179 |
}
|
180 |
}
|
181 |
}
|
182 |
+
if ($info['audio']['dataformat'] == 'mp4') {
|
183 |
$info['fileformat'] = 'mp4';
|
184 |
+
if (empty($info['video']['resolution_x'])) {
|
185 |
+
$info['mime_type'] = 'audio/mp4';
|
186 |
+
unset($info['video']['dataformat']);
|
187 |
+
} else {
|
188 |
+
$info['mime_type'] = 'video/mp4';
|
189 |
+
}
|
190 |
}
|
191 |
|
192 |
if (!$this->ReturnAtomData) {
|
199 |
if (empty($info['video']['dataformat']) && !empty($info['quicktime']['video'])) {
|
200 |
$info['video']['dataformat'] = 'quicktime';
|
201 |
}
|
202 |
+
if (isset($info['video']) && ($info['mime_type'] == 'audio/mp4') && empty($info['video']['resolution_x']) && empty($info['video']['resolution_y'])) {
|
203 |
+
unset($info['video']);
|
204 |
+
}
|
205 |
|
206 |
return true;
|
207 |
}
|
208 |
|
209 |
+
/**
|
210 |
+
* @param string $atomname
|
211 |
+
* @param int $atomsize
|
212 |
+
* @param string $atom_data
|
213 |
+
* @param int $baseoffset
|
214 |
+
* @param array $atomHierarchy
|
215 |
+
* @param bool $ParseAllPossibleAtoms
|
216 |
+
*
|
217 |
+
* @return array|false
|
218 |
+
*/
|
219 |
public function QuicktimeParseAtom($atomname, $atomsize, $atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) {
|
220 |
// http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm
|
221 |
// https://code.google.com/p/mp4v2/wiki/iTunesMetadata
|
222 |
|
223 |
$info = &$this->getid3->info;
|
224 |
|
225 |
+
$atom_parent = end($atomHierarchy); // not array_pop($atomHierarchy); see https://www.getid3.org/phpBB3/viewtopic.php?t=1717
|
226 |
array_push($atomHierarchy, $atomname);
|
227 |
$atom_structure['hierarchy'] = implode(' ', $atomHierarchy);
|
228 |
$atom_structure['name'] = $atomname;
|
229 |
$atom_structure['size'] = $atomsize;
|
230 |
$atom_structure['offset'] = $baseoffset;
|
231 |
+
if (substr($atomname, 0, 3) == "\x00\x00\x00") {
|
232 |
+
// https://github.com/JamesHeinrich/getID3/issues/139
|
233 |
+
$atomname = getid3_lib::BigEndian2Int($atomname);
|
234 |
+
$atom_structure['name'] = $atomname;
|
235 |
+
$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
|
236 |
+
} else {
|
237 |
+
switch ($atomname) {
|
238 |
+
case 'moov': // MOVie container atom
|
239 |
+
case 'trak': // TRAcK container atom
|
240 |
+
case 'clip': // CLIPping container atom
|
241 |
+
case 'matt': // track MATTe container atom
|
242 |
+
case 'edts': // EDiTS container atom
|
243 |
+
case 'tref': // Track REFerence container atom
|
244 |
+
case 'mdia': // MeDIA container atom
|
245 |
+
case 'minf': // Media INFormation container atom
|
246 |
+
case 'dinf': // Data INFormation container atom
|
247 |
+
case 'udta': // User DaTA container atom
|
248 |
+
case 'cmov': // Compressed MOVie container atom
|
249 |
+
case 'rmra': // Reference Movie Record Atom
|
250 |
+
case 'rmda': // Reference Movie Descriptor Atom
|
251 |
+
case 'gmhd': // Generic Media info HeaDer atom (seen on QTVR)
|
252 |
+
$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
|
253 |
+
break;
|
254 |
|
255 |
+
case 'ilst': // Item LiST container atom
|
256 |
+
if ($atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms)) {
|
257 |
+
// some "ilst" atoms contain data atoms that have a numeric name, and the data is far more accessible if the returned array is compacted
|
258 |
+
$allnumericnames = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
259 |
foreach ($atom_structure['subatoms'] as $subatomarray) {
|
260 |
+
if (!is_integer($subatomarray['name']) || (count($subatomarray['subatoms']) != 1)) {
|
261 |
+
$allnumericnames = false;
|
|
|
262 |
break;
|
263 |
}
|
264 |
}
|
265 |
+
if ($allnumericnames) {
|
266 |
+
$newData = array();
|
267 |
+
foreach ($atom_structure['subatoms'] as $subatomarray) {
|
268 |
+
foreach ($subatomarray['subatoms'] as $newData_subatomarray) {
|
269 |
+
unset($newData_subatomarray['hierarchy'], $newData_subatomarray['name']);
|
270 |
+
$newData[$subatomarray['name']] = $newData_subatomarray;
|
271 |
+
break;
|
272 |
+
}
|
273 |
+
}
|
274 |
+
$atom_structure['data'] = $newData;
|
275 |
+
unset($atom_structure['subatoms']);
|
276 |
+
}
|
277 |
}
|
278 |
+
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
279 |
|
280 |
+
case 'stbl': // Sample TaBLe container atom
|
281 |
+
$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
|
282 |
+
$isVideo = false;
|
283 |
+
$framerate = 0;
|
284 |
+
$framecount = 0;
|
285 |
+
foreach ($atom_structure['subatoms'] as $key => $value_array) {
|
286 |
+
if (isset($value_array['sample_description_table'])) {
|
287 |
+
foreach ($value_array['sample_description_table'] as $key2 => $value_array2) {
|
288 |
+
if (isset($value_array2['data_format'])) {
|
289 |
+
switch ($value_array2['data_format']) {
|
290 |
+
case 'avc1':
|
291 |
+
case 'mp4v':
|
292 |
+
// video data
|
293 |
+
$isVideo = true;
|
294 |
+
break;
|
295 |
+
case 'mp4a':
|
296 |
+
// audio data
|
297 |
+
break;
|
298 |
+
}
|
299 |
}
|
300 |
}
|
301 |
+
} elseif (isset($value_array['time_to_sample_table'])) {
|
302 |
+
foreach ($value_array['time_to_sample_table'] as $key2 => $value_array2) {
|
303 |
+
if (isset($value_array2['sample_count']) && isset($value_array2['sample_duration']) && ($value_array2['sample_duration'] > 0)) {
|
304 |
+
$framerate = round($info['quicktime']['time_scale'] / $value_array2['sample_duration'], 3);
|
305 |
+
$framecount = $value_array2['sample_count'];
|
306 |
+
}
|
307 |
}
|
308 |
}
|
309 |
}
|
310 |
+
if ($isVideo && $framerate) {
|
311 |
+
$info['quicktime']['video']['frame_rate'] = $framerate;
|
312 |
+
$info['video']['frame_rate'] = $info['quicktime']['video']['frame_rate'];
|
313 |
+
}
|
314 |
+
if ($isVideo && $framecount) {
|
315 |
+
$info['quicktime']['video']['frame_count'] = $framecount;
|
316 |
+
}
|
317 |
+
break;
|
|
|
|
|
318 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
319 |
|
320 |
+
case "\xA9".'alb': // ALBum
|
321 |
+
case "\xA9".'ART': //
|
322 |
+
case "\xA9".'art': // ARTist
|
323 |
+
case "\xA9".'aut': //
|
324 |
+
case "\xA9".'cmt': // CoMmenT
|
325 |
+
case "\xA9".'com': // COMposer
|
326 |
+
case "\xA9".'cpy': //
|
327 |
+
case "\xA9".'day': // content created year
|
328 |
+
case "\xA9".'dir': //
|
329 |
+
case "\xA9".'ed1': //
|
330 |
+
case "\xA9".'ed2': //
|
331 |
+
case "\xA9".'ed3': //
|
332 |
+
case "\xA9".'ed4': //
|
333 |
+
case "\xA9".'ed5': //
|
334 |
+
case "\xA9".'ed6': //
|
335 |
+
case "\xA9".'ed7': //
|
336 |
+
case "\xA9".'ed8': //
|
337 |
+
case "\xA9".'ed9': //
|
338 |
+
case "\xA9".'enc': //
|
339 |
+
case "\xA9".'fmt': //
|
340 |
+
case "\xA9".'gen': // GENre
|
341 |
+
case "\xA9".'grp': // GRouPing
|
342 |
+
case "\xA9".'hst': //
|
343 |
+
case "\xA9".'inf': //
|
344 |
+
case "\xA9".'lyr': // LYRics
|
345 |
+
case "\xA9".'mak': //
|
346 |
+
case "\xA9".'mod': //
|
347 |
+
case "\xA9".'nam': // full NAMe
|
348 |
+
case "\xA9".'ope': //
|
349 |
+
case "\xA9".'PRD': //
|
350 |
+
case "\xA9".'prf': //
|
351 |
+
case "\xA9".'req': //
|
352 |
+
case "\xA9".'src': //
|
353 |
+
case "\xA9".'swr': //
|
354 |
+
case "\xA9".'too': // encoder
|
355 |
+
case "\xA9".'trk': // TRacK
|
356 |
+
case "\xA9".'url': //
|
357 |
+
case "\xA9".'wrn': //
|
358 |
+
case "\xA9".'wrt': // WRiTer
|
359 |
+
case '----': // itunes specific
|
360 |
+
case 'aART': // Album ARTist
|
361 |
+
case 'akID': // iTunes store account type
|
362 |
+
case 'apID': // Purchase Account
|
363 |
+
case 'atID': //
|
364 |
+
case 'catg': // CaTeGory
|
365 |
+
case 'cmID': //
|
366 |
+
case 'cnID': //
|
367 |
+
case 'covr': // COVeR artwork
|
368 |
+
case 'cpil': // ComPILation
|
369 |
+
case 'cprt': // CoPyRighT
|
370 |
+
case 'desc': // DESCription
|
371 |
+
case 'disk': // DISK number
|
372 |
+
case 'egid': // Episode Global ID
|
373 |
+
case 'geID': //
|
374 |
+
case 'gnre': // GeNRE
|
375 |
+
case 'hdvd': // HD ViDeo
|
376 |
+
case 'keyw': // KEYWord
|
377 |
+
case 'ldes': // Long DEScription
|
378 |
+
case 'pcst': // PodCaST
|
379 |
+
case 'pgap': // GAPless Playback
|
380 |
+
case 'plID': //
|
381 |
+
case 'purd': // PURchase Date
|
382 |
+
case 'purl': // Podcast URL
|
383 |
+
case 'rati': //
|
384 |
+
case 'rndu': //
|
385 |
+
case 'rpdu': //
|
386 |
+
case 'rtng': // RaTiNG
|
387 |
+
case 'sfID': // iTunes store country
|
388 |
+
case 'soaa': // SOrt Album Artist
|
389 |
+
case 'soal': // SOrt ALbum
|
390 |
+
case 'soar': // SOrt ARtist
|
391 |
+
case 'soco': // SOrt COmposer
|
392 |
+
case 'sonm': // SOrt NaMe
|
393 |
+
case 'sosn': // SOrt Show Name
|
394 |
+
case 'stik': //
|
395 |
+
case 'tmpo': // TeMPO (BPM)
|
396 |
+
case 'trkn': // TRacK Number
|
397 |
+
case 'tven': // tvEpisodeID
|
398 |
+
case 'tves': // TV EpiSode
|
399 |
+
case 'tvnn': // TV Network Name
|
400 |
+
case 'tvsh': // TV SHow Name
|
401 |
+
case 'tvsn': // TV SeasoN
|
402 |
+
if ($atom_parent == 'udta') {
|
403 |
+
// User data atom handler
|
404 |
+
$atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
|
405 |
+
$atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2));
|
406 |
+
$atom_structure['data'] = substr($atom_data, 4);
|
407 |
+
|
408 |
+
$atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']);
|
409 |
+
if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) {
|
410 |
+
$info['comments']['language'][] = $atom_structure['language'];
|
411 |
}
|
412 |
} else {
|
413 |
+
// Apple item list box atom handler
|
414 |
+
$atomoffset = 0;
|
415 |
+
if (substr($atom_data, 2, 2) == "\x10\xB5") {
|
416 |
+
// not sure what it means, but observed on iPhone4 data.
|
417 |
+
// Each $atom_data has 2 bytes of datasize, plus 0x10B5, then data
|
418 |
+
while ($atomoffset < strlen($atom_data)) {
|
419 |
+
$boxsmallsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 2));
|
420 |
+
$boxsmalltype = substr($atom_data, $atomoffset + 2, 2);
|
421 |
+
$boxsmalldata = substr($atom_data, $atomoffset + 4, $boxsmallsize);
|
422 |
+
if ($boxsmallsize <= 1) {
|
423 |
+
$this->warning('Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset));
|
424 |
+
$atom_structure['data'] = null;
|
425 |
+
$atomoffset = strlen($atom_data);
|
426 |
+
break;
|
427 |
+
}
|
428 |
+
switch ($boxsmalltype) {
|
429 |
+
case "\x10\xB5":
|
430 |
+
$atom_structure['data'] = $boxsmalldata;
|
431 |
+
break;
|
432 |
+
default:
|
433 |
+
$this->warning('Unknown QuickTime smallbox type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxsmalltype).'" ('.trim(getid3_lib::PrintHexBytes($boxsmalltype)).') at offset '.$baseoffset);
|
434 |
+
$atom_structure['data'] = $atom_data;
|
435 |
+
break;
|
436 |
+
}
|
437 |
+
$atomoffset += (4 + $boxsmallsize);
|
438 |
}
|
439 |
+
} else {
|
440 |
+
while ($atomoffset < strlen($atom_data)) {
|
441 |
+
$boxsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 4));
|
442 |
+
$boxtype = substr($atom_data, $atomoffset + 4, 4);
|
443 |
+
$boxdata = substr($atom_data, $atomoffset + 8, $boxsize - 8);
|
444 |
+
if ($boxsize <= 1) {
|
445 |
+
$this->warning('Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset));
|
446 |
+
$atom_structure['data'] = null;
|
447 |
+
$atomoffset = strlen($atom_data);
|
448 |
break;
|
449 |
+
}
|
450 |
+
$atomoffset += $boxsize;
|
451 |
|
452 |
+
switch ($boxtype) {
|
453 |
+
case 'mean':
|
454 |
+
case 'name':
|
455 |
+
$atom_structure[$boxtype] = substr($boxdata, 4);
|
456 |
+
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
457 |
|
458 |
+
case 'data':
|
459 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($boxdata, 0, 1));
|
460 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($boxdata, 1, 3));
|
461 |
+
switch ($atom_structure['flags_raw']) {
|
462 |
+
case 0: // data flag
|
463 |
+
case 21: // tmpo/cpil flag
|
464 |
+
switch ($atomname) {
|
465 |
+
case 'cpil':
|
466 |
+
case 'hdvd':
|
467 |
+
case 'pcst':
|
468 |
+
case 'pgap':
|
469 |
+
// 8-bit integer (boolean)
|
470 |
+
$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
|
471 |
+
break;
|
472 |
+
|
473 |
+
case 'tmpo':
|
474 |
+
// 16-bit integer
|
475 |
+
$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 2));
|
476 |
+
break;
|
477 |
+
|
478 |
+
case 'disk':
|
479 |
+
case 'trkn':
|
480 |
+
// binary
|
481 |
+
$num = getid3_lib::BigEndian2Int(substr($boxdata, 10, 2));
|
482 |
+
$num_total = getid3_lib::BigEndian2Int(substr($boxdata, 12, 2));
|
483 |
+
$atom_structure['data'] = empty($num) ? '' : $num;
|
484 |
+
$atom_structure['data'] .= empty($num_total) ? '' : '/'.$num_total;
|
485 |
+
break;
|
486 |
+
|
487 |
+
case 'gnre':
|
488 |
+
// enum
|
489 |
+
$GenreID = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
|
490 |
+
$atom_structure['data'] = getid3_id3v1::LookupGenreName($GenreID - 1);
|
491 |
+
break;
|
492 |
+
|
493 |
+
case 'rtng':
|
494 |
+
// 8-bit integer
|
495 |
+
$atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
|
496 |
+
$atom_structure['data'] = $this->QuicktimeContentRatingLookup($atom_structure[$atomname]);
|
497 |
+
break;
|
498 |
+
|
499 |
+
case 'stik':
|
500 |
+
// 8-bit integer (enum)
|
501 |
+
$atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
|
502 |
+
$atom_structure['data'] = $this->QuicktimeSTIKLookup($atom_structure[$atomname]);
|
503 |
+
break;
|
504 |
+
|
505 |
+
case 'sfID':
|
506 |
+
// 32-bit integer
|
507 |
+
$atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
|
508 |
+
$atom_structure['data'] = $this->QuicktimeStoreFrontCodeLookup($atom_structure[$atomname]);
|
509 |
+
break;
|
510 |
+
|
511 |
+
case 'egid':
|
512 |
+
case 'purl':
|
513 |
+
$atom_structure['data'] = substr($boxdata, 8);
|
514 |
+
break;
|
515 |
+
|
516 |
+
case 'plID':
|
517 |
+
// 64-bit integer
|
518 |
+
$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 8));
|
519 |
+
break;
|
520 |
+
|
521 |
+
case 'covr':
|
522 |
+
$atom_structure['data'] = substr($boxdata, 8);
|
523 |
+
// not a foolproof check, but better than nothing
|
524 |
+
if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) {
|
525 |
+
$atom_structure['image_mime'] = 'image/jpeg';
|
526 |
+
} elseif (preg_match('#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure['data'])) {
|
527 |
+
$atom_structure['image_mime'] = 'image/png';
|
528 |
+
} elseif (preg_match('#^GIF#', $atom_structure['data'])) {
|
529 |
+
$atom_structure['image_mime'] = 'image/gif';
|
530 |
+
}
|
531 |
+
break;
|
532 |
+
|
533 |
+
case 'atID':
|
534 |
+
case 'cnID':
|
535 |
+
case 'geID':
|
536 |
+
case 'tves':
|
537 |
+
case 'tvsn':
|
538 |
+
default:
|
539 |
+
// 32-bit integer
|
540 |
+
$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
|
541 |
}
|
542 |
+
break;
|
543 |
+
|
544 |
+
case 1: // text flag
|
545 |
+
case 13: // image flag
|
546 |
+
default:
|
547 |
+
$atom_structure['data'] = substr($boxdata, 8);
|
548 |
+
if ($atomname == 'covr') {
|
549 |
+
// not a foolproof check, but better than nothing
|
550 |
+
if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) {
|
551 |
+
$atom_structure['image_mime'] = 'image/jpeg';
|
552 |
+
} elseif (preg_match('#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure['data'])) {
|
553 |
+
$atom_structure['image_mime'] = 'image/png';
|
554 |
+
} elseif (preg_match('#^GIF#', $atom_structure['data'])) {
|
555 |
+
$atom_structure['image_mime'] = 'image/gif';
|
556 |
+
}
|
557 |
+
}
|
558 |
+
break;
|
559 |
|
560 |
+
}
|
561 |
+
break;
|
562 |
|
563 |
+
default:
|
564 |
+
$this->warning('Unknown QuickTime box type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxtype).'" ('.trim(getid3_lib::PrintHexBytes($boxtype)).') at offset '.$baseoffset);
|
565 |
+
$atom_structure['data'] = $atom_data;
|
566 |
|
567 |
+
}
|
568 |
}
|
569 |
}
|
570 |
}
|
571 |
+
$this->CopyToAppropriateCommentsSection($atomname, $atom_structure['data'], $atom_structure['name']);
|
572 |
+
break;
|
|
|
573 |
|
574 |
|
575 |
+
case 'play': // auto-PLAY atom
|
576 |
+
$atom_structure['autoplay'] = (bool) getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
577 |
|
578 |
+
$info['quicktime']['autoplay'] = $atom_structure['autoplay'];
|
579 |
+
break;
|
580 |
|
581 |
|
582 |
+
case 'WLOC': // Window LOCation atom
|
583 |
+
$atom_structure['location_x'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
|
584 |
+
$atom_structure['location_y'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2));
|
585 |
+
break;
|
586 |
|
587 |
|
588 |
+
case 'LOOP': // LOOPing atom
|
589 |
+
case 'SelO': // play SELection Only atom
|
590 |
+
case 'AllF': // play ALL Frames atom
|
591 |
+
$atom_structure['data'] = getid3_lib::BigEndian2Int($atom_data);
|
592 |
+
break;
|
593 |
|
594 |
|
595 |
+
case 'name': //
|
596 |
+
case 'MCPS': // Media Cleaner PRo
|
597 |
+
case '@PRM': // adobe PReMiere version
|
598 |
+
case '@PRQ': // adobe PRemiere Quicktime version
|
599 |
+
$atom_structure['data'] = $atom_data;
|
600 |
+
break;
|
601 |
|
602 |
|
603 |
+
case 'cmvd': // Compressed MooV Data atom
|
604 |
+
// Code by ubergeekØubergeek*tv based on information from
|
605 |
+
// http://developer.apple.com/quicktime/icefloe/dispatch012.html
|
606 |
+
$atom_structure['unCompressedSize'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
|
607 |
|
608 |
+
$CompressedFileData = substr($atom_data, 4);
|
609 |
+
if ($UncompressedHeader = @gzuncompress($CompressedFileData)) {
|
610 |
+
$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($UncompressedHeader, 0, $atomHierarchy, $ParseAllPossibleAtoms);
|
611 |
+
} else {
|
612 |
+
$this->warning('Error decompressing compressed MOV atom at offset '.$atom_structure['offset']);
|
613 |
+
}
|
614 |
+
break;
|
615 |
|
616 |
|
617 |
+
case 'dcom': // Data COMpression atom
|
618 |
+
$atom_structure['compression_id'] = $atom_data;
|
619 |
+
$atom_structure['compression_text'] = $this->QuicktimeDCOMLookup($atom_data);
|
620 |
+
break;
|
621 |
|
622 |
|
623 |
+
case 'rdrf': // Reference movie Data ReFerence atom
|
624 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
625 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
|
626 |
+
$atom_structure['flags']['internal_data'] = (bool) ($atom_structure['flags_raw'] & 0x000001);
|
627 |
|
628 |
+
$atom_structure['reference_type_name'] = substr($atom_data, 4, 4);
|
629 |
+
$atom_structure['reference_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4));
|
630 |
+
switch ($atom_structure['reference_type_name']) {
|
631 |
+
case 'url ':
|
632 |
+
$atom_structure['url'] = $this->NoNullString(substr($atom_data, 12));
|
633 |
+
break;
|
634 |
|
635 |
+
case 'alis':
|
636 |
+
$atom_structure['file_alias'] = substr($atom_data, 12);
|
637 |
+
break;
|
638 |
|
639 |
+
case 'rsrc':
|
640 |
+
$atom_structure['resource_alias'] = substr($atom_data, 12);
|
641 |
+
break;
|
642 |
|
643 |
+
default:
|
644 |
+
$atom_structure['data'] = substr($atom_data, 12);
|
645 |
+
break;
|
646 |
+
}
|
647 |
+
break;
|
648 |
|
649 |
|
650 |
+
case 'rmqu': // Reference Movie QUality atom
|
651 |
+
$atom_structure['movie_quality'] = getid3_lib::BigEndian2Int($atom_data);
|
652 |
+
break;
|
653 |
|
654 |
|
655 |
+
case 'rmcs': // Reference Movie Cpu Speed atom
|
656 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
657 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
658 |
+
$atom_structure['cpu_speed_rating'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2));
|
659 |
+
break;
|
660 |
|
661 |
|
662 |
+
case 'rmvc': // Reference Movie Version Check atom
|
663 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
664 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
665 |
+
$atom_structure['gestalt_selector'] = substr($atom_data, 4, 4);
|
666 |
+
$atom_structure['gestalt_value_mask'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4));
|
667 |
+
$atom_structure['gestalt_value'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
|
668 |
+
$atom_structure['gestalt_check_type'] = getid3_lib::BigEndian2Int(substr($atom_data, 14, 2));
|
669 |
+
break;
|
670 |
|
671 |
|
672 |
+
case 'rmcd': // Reference Movie Component check atom
|
673 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
674 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
675 |
+
$atom_structure['component_type'] = substr($atom_data, 4, 4);
|
676 |
+
$atom_structure['component_subtype'] = substr($atom_data, 8, 4);
|
677 |
+
$atom_structure['component_manufacturer'] = substr($atom_data, 12, 4);
|
678 |
+
$atom_structure['component_flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
|
679 |
+
$atom_structure['component_flags_mask'] = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4));
|
680 |
+
$atom_structure['component_min_version'] = getid3_lib::BigEndian2Int(substr($atom_data, 24, 4));
|
681 |
+
break;
|
682 |
|
683 |
|
684 |
+
case 'rmdr': // Reference Movie Data Rate atom
|
685 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
686 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
687 |
+
$atom_structure['data_rate'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
|
688 |
|
689 |
+
$atom_structure['data_rate_bps'] = $atom_structure['data_rate'] * 10;
|
690 |
+
break;
|
691 |
|
692 |
|
693 |
+
case 'rmla': // Reference Movie Language Atom
|
694 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
695 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
696 |
+
$atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2));
|
697 |
|
698 |
+
$atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']);
|
699 |
+
if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) {
|
700 |
+
$info['comments']['language'][] = $atom_structure['language'];
|
701 |
+
}
|
702 |
+
break;
|
703 |
|
704 |
|
705 |
+
case 'ptv ': // Print To Video - defines a movie's full screen mode
|
706 |
+
// http://developer.apple.com/documentation/QuickTime/APIREF/SOURCESIV/at_ptv-_pg.htm
|
707 |
+
$atom_structure['display_size_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
|
708 |
+
$atom_structure['reserved_1'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); // hardcoded: 0x0000
|
709 |
+
$atom_structure['reserved_2'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x0000
|
710 |
+
$atom_structure['slide_show_flag'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 1));
|
711 |
+
$atom_structure['play_on_open_flag'] = getid3_lib::BigEndian2Int(substr($atom_data, 7, 1));
|
712 |
+
|
713 |
+
$atom_structure['flags']['play_on_open'] = (bool) $atom_structure['play_on_open_flag'];
|
714 |
+
$atom_structure['flags']['slide_show'] = (bool) $atom_structure['slide_show_flag'];
|
715 |
+
|
716 |
+
$ptv_lookup[0] = 'normal';
|
717 |
+
$ptv_lookup[1] = 'double';
|
718 |
+
$ptv_lookup[2] = 'half';
|
719 |
+
$ptv_lookup[3] = 'full';
|
720 |
+
$ptv_lookup[4] = 'current';
|
721 |
+
if (isset($ptv_lookup[$atom_structure['display_size_raw']])) {
|
722 |
+
$atom_structure['display_size'] = $ptv_lookup[$atom_structure['display_size_raw']];
|
723 |
+
} else {
|
724 |
+
$this->warning('unknown "ptv " display constant ('.$atom_structure['display_size_raw'].')');
|
725 |
+
}
|
726 |
+
break;
|
727 |
|
728 |
|
729 |
+
case 'stsd': // Sample Table Sample Description atom
|
730 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
731 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
732 |
+
$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
733 |
|
734 |
+
// see: https://github.com/JamesHeinrich/getID3/issues/111
|
735 |
+
// Some corrupt files have been known to have high bits set in the number_entries field
|
736 |
+
// This field shouldn't really need to be 32-bits, values stores are likely in the range 1-100000
|
737 |
+
// Workaround: mask off the upper byte and throw a warning if it's nonzero
|
738 |
+
if ($atom_structure['number_entries'] > 0x000FFFFF) {
|
739 |
+
if ($atom_structure['number_entries'] > 0x00FFFFFF) {
|
740 |
+
$this->warning('"stsd" atom contains improbably large number_entries (0x'.getid3_lib::PrintHexBytes(substr($atom_data, 4, 4), true, false).' = '.$atom_structure['number_entries'].'), probably in error. Ignoring upper byte and interpreting this as 0x'.getid3_lib::PrintHexBytes(substr($atom_data, 5, 3), true, false).' = '.($atom_structure['number_entries'] & 0x00FFFFFF));
|
741 |
+
$atom_structure['number_entries'] = ($atom_structure['number_entries'] & 0x00FFFFFF);
|
742 |
+
} else {
|
743 |
+
$this->warning('"stsd" atom contains improbably large number_entries (0x'.getid3_lib::PrintHexBytes(substr($atom_data, 4, 4), true, false).' = '.$atom_structure['number_entries'].'), probably in error. Please report this to info@getid3.org referencing bug report #111');
|
744 |
+
}
|
745 |
+
}
|
746 |
|
747 |
+
$stsdEntriesDataOffset = 8;
|
748 |
+
for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
|
749 |
+
$atom_structure['sample_description_table'][$i]['size'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 4));
|
750 |
+
$stsdEntriesDataOffset += 4;
|
751 |
+
$atom_structure['sample_description_table'][$i]['data_format'] = substr($atom_data, $stsdEntriesDataOffset, 4);
|
752 |
+
$stsdEntriesDataOffset += 4;
|
753 |
+
$atom_structure['sample_description_table'][$i]['reserved'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 6));
|
754 |
+
$stsdEntriesDataOffset += 6;
|
755 |
+
$atom_structure['sample_description_table'][$i]['reference_index'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 2));
|
756 |
+
$stsdEntriesDataOffset += 2;
|
757 |
+
$atom_structure['sample_description_table'][$i]['data'] = substr($atom_data, $stsdEntriesDataOffset, ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2));
|
758 |
+
$stsdEntriesDataOffset += ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2);
|
759 |
+
|
760 |
+
$atom_structure['sample_description_table'][$i]['encoder_version'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 0, 2));
|
761 |
+
$atom_structure['sample_description_table'][$i]['encoder_revision'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 2, 2));
|
762 |
+
$atom_structure['sample_description_table'][$i]['encoder_vendor'] = substr($atom_structure['sample_description_table'][$i]['data'], 4, 4);
|
763 |
+
|
764 |
+
switch ($atom_structure['sample_description_table'][$i]['encoder_vendor']) {
|
765 |
+
|
766 |
+
case "\x00\x00\x00\x00":
|
767 |
+
// audio tracks
|
768 |
+
$atom_structure['sample_description_table'][$i]['audio_channels'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 8, 2));
|
769 |
+
$atom_structure['sample_description_table'][$i]['audio_bit_depth'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 10, 2));
|
770 |
+
$atom_structure['sample_description_table'][$i]['audio_compression_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12, 2));
|
771 |
+
$atom_structure['sample_description_table'][$i]['audio_packet_size'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 14, 2));
|
772 |
+
$atom_structure['sample_description_table'][$i]['audio_sample_rate'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 16, 4));
|
773 |
+
|
774 |
+
// video tracks
|
775 |
+
// http://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap3/qtff3.html
|
776 |
+
$atom_structure['sample_description_table'][$i]['temporal_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 8, 4));
|
777 |
+
$atom_structure['sample_description_table'][$i]['spatial_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12, 4));
|
778 |
+
$atom_structure['sample_description_table'][$i]['width'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16, 2));
|
779 |
+
$atom_structure['sample_description_table'][$i]['height'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18, 2));
|
780 |
+
$atom_structure['sample_description_table'][$i]['resolution_x'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24, 4));
|
781 |
+
$atom_structure['sample_description_table'][$i]['resolution_y'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 28, 4));
|
782 |
+
$atom_structure['sample_description_table'][$i]['data_size'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32, 4));
|
783 |
+
$atom_structure['sample_description_table'][$i]['frame_count'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 36, 2));
|
784 |
+
$atom_structure['sample_description_table'][$i]['compressor_name'] = substr($atom_structure['sample_description_table'][$i]['data'], 38, 4);
|
785 |
+
$atom_structure['sample_description_table'][$i]['pixel_depth'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 42, 2));
|
786 |
+
$atom_structure['sample_description_table'][$i]['color_table_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 44, 2));
|
787 |
+
|
788 |
+
switch ($atom_structure['sample_description_table'][$i]['data_format']) {
|
789 |
+
case '2vuY':
|
790 |
+
case 'avc1':
|
791 |
+
case 'cvid':
|
792 |
+
case 'dvc ':
|
793 |
+
case 'dvcp':
|
794 |
+
case 'gif ':
|
795 |
+
case 'h263':
|
796 |
+
case 'jpeg':
|
797 |
+
case 'kpcd':
|
798 |
+
case 'mjpa':
|
799 |
+
case 'mjpb':
|
800 |
+
case 'mp4v':
|
801 |
+
case 'png ':
|
802 |
+
case 'raw ':
|
803 |
+
case 'rle ':
|
804 |
+
case 'rpza':
|
805 |
+
case 'smc ':
|
806 |
+
case 'SVQ1':
|
807 |
+
case 'SVQ3':
|
808 |
+
case 'tiff':
|
809 |
+
case 'v210':
|
810 |
+
case 'v216':
|
811 |
+
case 'v308':
|
812 |
+
case 'v408':
|
813 |
+
case 'v410':
|
814 |
+
case 'yuv2':
|
815 |
+
$info['fileformat'] = 'mp4';
|
816 |
+
$info['video']['fourcc'] = $atom_structure['sample_description_table'][$i]['data_format'];
|
817 |
+
if ($this->QuicktimeVideoCodecLookup($info['video']['fourcc'])) {
|
818 |
+
$info['video']['fourcc_lookup'] = $this->QuicktimeVideoCodecLookup($info['video']['fourcc']);
|
819 |
+
}
|
820 |
+
|
821 |
+
// https://www.getid3.org/phpBB3/viewtopic.php?t=1550
|
822 |
+
//if ((!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['width'])) && (empty($info['video']['resolution_x']) || empty($info['video']['resolution_y']) || (number_format($info['video']['resolution_x'], 6) != number_format(round($info['video']['resolution_x']), 6)) || (number_format($info['video']['resolution_y'], 6) != number_format(round($info['video']['resolution_y']), 6)))) { // ugly check for floating point numbers
|
823 |
+
if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['height'])) {
|
824 |
+
// assume that values stored here are more important than values stored in [tkhd] atom
|
825 |
+
$info['video']['resolution_x'] = $atom_structure['sample_description_table'][$i]['width'];
|
826 |
+
$info['video']['resolution_y'] = $atom_structure['sample_description_table'][$i]['height'];
|
827 |
+
$info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x'];
|
828 |
+
$info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y'];
|
829 |
+
}
|
830 |
+
break;
|
831 |
|
832 |
+
case 'qtvr':
|
833 |
+
$info['video']['dataformat'] = 'quicktimevr';
|
834 |
+
break;
|
835 |
|
836 |
+
case 'mp4a':
|
837 |
+
default:
|
838 |
+
$info['quicktime']['audio']['codec'] = $this->QuicktimeAudioCodecLookup($atom_structure['sample_description_table'][$i]['data_format']);
|
839 |
+
$info['quicktime']['audio']['sample_rate'] = $atom_structure['sample_description_table'][$i]['audio_sample_rate'];
|
840 |
+
$info['quicktime']['audio']['channels'] = $atom_structure['sample_description_table'][$i]['audio_channels'];
|
841 |
+
$info['quicktime']['audio']['bit_depth'] = $atom_structure['sample_description_table'][$i]['audio_bit_depth'];
|
842 |
+
$info['audio']['codec'] = $info['quicktime']['audio']['codec'];
|
843 |
+
$info['audio']['sample_rate'] = $info['quicktime']['audio']['sample_rate'];
|
844 |
+
$info['audio']['channels'] = $info['quicktime']['audio']['channels'];
|
845 |
+
$info['audio']['bits_per_sample'] = $info['quicktime']['audio']['bit_depth'];
|
846 |
+
switch ($atom_structure['sample_description_table'][$i]['data_format']) {
|
847 |
+
case 'raw ': // PCM
|
848 |
+
case 'alac': // Apple Lossless Audio Codec
|
849 |
+
case 'sowt': // signed/two's complement (Little Endian)
|
850 |
+
case 'twos': // signed/two's complement (Big Endian)
|
851 |
+
case 'in24': // 24-bit Integer
|
852 |
+
case 'in32': // 32-bit Integer
|
853 |
+
case 'fl32': // 32-bit Floating Point
|
854 |
+
case 'fl64': // 64-bit Floating Point
|
855 |
+
$info['audio']['lossless'] = $info['quicktime']['audio']['lossless'] = true;
|
856 |
+
$info['audio']['bitrate'] = $info['quicktime']['audio']['bitrate'] = $info['audio']['channels'] * $info['audio']['bits_per_sample'] * $info['audio']['sample_rate'];
|
857 |
+
break;
|
858 |
+
default:
|
859 |
+
$info['audio']['lossless'] = false;
|
860 |
+
break;
|
861 |
+
}
|
862 |
+
break;
|
863 |
+
}
|
864 |
+
break;
|
865 |
|
866 |
+
default:
|
867 |
+
switch ($atom_structure['sample_description_table'][$i]['data_format']) {
|
868 |
+
case 'mp4s':
|
869 |
+
$info['fileformat'] = 'mp4';
|
870 |
+
break;
|
871 |
|
872 |
+
default:
|
873 |
+
// video atom
|
874 |
+
$atom_structure['sample_description_table'][$i]['video_temporal_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 8, 4));
|
875 |
+
$atom_structure['sample_description_table'][$i]['video_spatial_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12, 4));
|
876 |
+
$atom_structure['sample_description_table'][$i]['video_frame_width'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16, 2));
|
877 |
+
$atom_structure['sample_description_table'][$i]['video_frame_height'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18, 2));
|
878 |
+
$atom_structure['sample_description_table'][$i]['video_resolution_x'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 20, 4));
|
879 |
+
$atom_structure['sample_description_table'][$i]['video_resolution_y'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24, 4));
|
880 |
+
$atom_structure['sample_description_table'][$i]['video_data_size'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 28, 4));
|
881 |
+
$atom_structure['sample_description_table'][$i]['video_frame_count'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32, 2));
|
882 |
+
$atom_structure['sample_description_table'][$i]['video_encoder_name_len'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 34, 1));
|
883 |
+
$atom_structure['sample_description_table'][$i]['video_encoder_name'] = substr($atom_structure['sample_description_table'][$i]['data'], 35, $atom_structure['sample_description_table'][$i]['video_encoder_name_len']);
|
884 |
+
$atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 66, 2));
|
885 |
+
$atom_structure['sample_description_table'][$i]['video_color_table_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 68, 2));
|
886 |
+
|
887 |
+
$atom_structure['sample_description_table'][$i]['video_pixel_color_type'] = (($atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] > 32) ? 'grayscale' : 'color');
|
888 |
+
$atom_structure['sample_description_table'][$i]['video_pixel_color_name'] = $this->QuicktimeColorNameLookup($atom_structure['sample_description_table'][$i]['video_pixel_color_depth']);
|
889 |
+
|
890 |
+
if ($atom_structure['sample_description_table'][$i]['video_pixel_color_name'] != 'invalid') {
|
891 |
+
$info['quicktime']['video']['codec_fourcc'] = $atom_structure['sample_description_table'][$i]['data_format'];
|
892 |
+
$info['quicktime']['video']['codec_fourcc_lookup'] = $this->QuicktimeVideoCodecLookup($atom_structure['sample_description_table'][$i]['data_format']);
|
893 |
+
$info['quicktime']['video']['codec'] = (($atom_structure['sample_description_table'][$i]['video_encoder_name_len'] > 0) ? $atom_structure['sample_description_table'][$i]['video_encoder_name'] : $atom_structure['sample_description_table'][$i]['data_format']);
|
894 |
+
$info['quicktime']['video']['color_depth'] = $atom_structure['sample_description_table'][$i]['video_pixel_color_depth'];
|
895 |
+
$info['quicktime']['video']['color_depth_name'] = $atom_structure['sample_description_table'][$i]['video_pixel_color_name'];
|
896 |
+
|
897 |
+
$info['video']['codec'] = $info['quicktime']['video']['codec'];
|
898 |
+
$info['video']['bits_per_sample'] = $info['quicktime']['video']['color_depth'];
|
899 |
+
}
|
900 |
+
$info['video']['lossless'] = false;
|
901 |
+
$info['video']['pixel_aspect_ratio'] = (float) 1;
|
902 |
+
break;
|
903 |
+
}
|
904 |
+
break;
|
905 |
+
}
|
906 |
+
switch (strtolower($atom_structure['sample_description_table'][$i]['data_format'])) {
|
907 |
+
case 'mp4a':
|
908 |
+
$info['audio']['dataformat'] = 'mp4';
|
909 |
+
$info['quicktime']['audio']['codec'] = 'mp4';
|
910 |
+
break;
|
911 |
|
912 |
+
case '3ivx':
|
913 |
+
case '3iv1':
|
914 |
+
case '3iv2':
|
915 |
+
$info['video']['dataformat'] = '3ivx';
|
916 |
+
break;
|
917 |
|
918 |
+
case 'xvid':
|
919 |
+
$info['video']['dataformat'] = 'xvid';
|
920 |
+
break;
|
921 |
|
922 |
+
case 'mp4v':
|
923 |
+
$info['video']['dataformat'] = 'mpeg4';
|
924 |
+
break;
|
925 |
|
926 |
+
case 'divx':
|
927 |
+
case 'div1':
|
928 |
+
case 'div2':
|
929 |
+
case 'div3':
|
930 |
+
case 'div4':
|
931 |
+
case 'div5':
|
932 |
+
case 'div6':
|
933 |
+
$info['video']['dataformat'] = 'divx';
|
934 |
+
break;
|
935 |
|
936 |
+
default:
|
937 |
+
// do nothing
|
938 |
+
break;
|
939 |
+
}
|
940 |
+
unset($atom_structure['sample_description_table'][$i]['data']);
|
941 |
}
|
942 |
+
break;
|
|
|
|
|
943 |
|
944 |
|
945 |
+
case 'stts': // Sample Table Time-to-Sample atom
|
946 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
947 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
948 |
+
$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
|
949 |
+
$sttsEntriesDataOffset = 8;
|
950 |
+
//$FrameRateCalculatorArray = array();
|
951 |
+
$frames_count = 0;
|
952 |
|
953 |
+
$max_stts_entries_to_scan = ($info['php_memory_limit'] ? min(floor($this->getid3->memory_limit / 10000), $atom_structure['number_entries']) : $atom_structure['number_entries']);
|
954 |
+
if ($max_stts_entries_to_scan < $atom_structure['number_entries']) {
|
955 |
+
$this->warning('QuickTime atom "stts" has '.$atom_structure['number_entries'].' but only scanning the first '.$max_stts_entries_to_scan.' entries due to limited PHP memory available ('.floor($this->getid3->memory_limit / 1048576).'MB).');
|
956 |
+
}
|
957 |
+
for ($i = 0; $i < $max_stts_entries_to_scan; $i++) {
|
958 |
+
$atom_structure['time_to_sample_table'][$i]['sample_count'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
|
959 |
+
$sttsEntriesDataOffset += 4;
|
960 |
+
$atom_structure['time_to_sample_table'][$i]['sample_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
|
961 |
+
$sttsEntriesDataOffset += 4;
|
962 |
+
|
963 |
+
$frames_count += $atom_structure['time_to_sample_table'][$i]['sample_count'];
|
964 |
+
|
965 |
+
// THIS SECTION REPLACED WITH CODE IN "stbl" ATOM
|
966 |
+
//if (!empty($info['quicktime']['time_scale']) && ($atom_structure['time_to_sample_table'][$i]['sample_duration'] > 0)) {
|
967 |
+
// $stts_new_framerate = $info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'];
|
968 |
+
// if ($stts_new_framerate <= 60) {
|
969 |
+
// // some atoms have durations of "1" giving a very large framerate, which probably is not right
|
970 |
+
// $info['video']['frame_rate'] = max($info['video']['frame_rate'], $stts_new_framerate);
|
971 |
+
// }
|
972 |
+
//}
|
973 |
+
//
|
974 |
+
//$FrameRateCalculatorArray[($info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'])] += $atom_structure['time_to_sample_table'][$i]['sample_count'];
|
975 |
+
}
|
976 |
+
$info['quicktime']['stts_framecount'][] = $frames_count;
|
977 |
+
//$sttsFramesTotal = 0;
|
978 |
+
//$sttsSecondsTotal = 0;
|
979 |
+
//foreach ($FrameRateCalculatorArray as $frames_per_second => $frame_count) {
|
980 |
+
// if (($frames_per_second > 60) || ($frames_per_second < 1)) {
|
981 |
+
// // not video FPS information, probably audio information
|
982 |
+
// $sttsFramesTotal = 0;
|
983 |
+
// $sttsSecondsTotal = 0;
|
984 |
+
// break;
|
985 |
// }
|
986 |
+
// $sttsFramesTotal += $frame_count;
|
987 |
+
// $sttsSecondsTotal += $frame_count / $frames_per_second;
|
988 |
//}
|
989 |
+
//if (($sttsFramesTotal > 0) && ($sttsSecondsTotal > 0)) {
|
990 |
+
// if (($sttsFramesTotal / $sttsSecondsTotal) > $info['video']['frame_rate']) {
|
991 |
+
// $info['video']['frame_rate'] = $sttsFramesTotal / $sttsSecondsTotal;
|
992 |
+
// }
|
993 |
+
//}
|
994 |
+
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
995 |
|
996 |
|
997 |
+
case 'stss': // Sample Table Sync Sample (key frames) atom
|
998 |
+
if ($ParseAllPossibleAtoms) {
|
999 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1000 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
1001 |
+
$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
|
1002 |
+
$stssEntriesDataOffset = 8;
|
1003 |
+
for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
|
1004 |
+
$atom_structure['time_to_sample_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stssEntriesDataOffset, 4));
|
1005 |
+
$stssEntriesDataOffset += 4;
|
1006 |
+
}
|
1007 |
}
|
1008 |
+
break;
|
|
|
1009 |
|
1010 |
|
1011 |
+
case 'stsc': // Sample Table Sample-to-Chunk atom
|
1012 |
+
if ($ParseAllPossibleAtoms) {
|
1013 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1014 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
1015 |
+
$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
|
1016 |
+
$stscEntriesDataOffset = 8;
|
1017 |
+
for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
|
1018 |
+
$atom_structure['sample_to_chunk_table'][$i]['first_chunk'] = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
|
1019 |
+
$stscEntriesDataOffset += 4;
|
1020 |
+
$atom_structure['sample_to_chunk_table'][$i]['samples_per_chunk'] = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
|
1021 |
+
$stscEntriesDataOffset += 4;
|
1022 |
+
$atom_structure['sample_to_chunk_table'][$i]['sample_description'] = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
|
1023 |
+
$stscEntriesDataOffset += 4;
|
1024 |
+
}
|
1025 |
}
|
1026 |
+
break;
|
|
|
1027 |
|
1028 |
|
1029 |
+
case 'stsz': // Sample Table SiZe atom
|
1030 |
+
if ($ParseAllPossibleAtoms) {
|
1031 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1032 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
1033 |
+
$atom_structure['sample_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
|
1034 |
+
$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4));
|
1035 |
+
$stszEntriesDataOffset = 12;
|
1036 |
+
if ($atom_structure['sample_size'] == 0) {
|
1037 |
+
for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
|
1038 |
+
$atom_structure['sample_size_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stszEntriesDataOffset, 4));
|
1039 |
+
$stszEntriesDataOffset += 4;
|
1040 |
+
}
|
1041 |
+
}
|
1042 |
+
}
|
1043 |
+
break;
|
1044 |
+
|
1045 |
+
|
1046 |
+
case 'stco': // Sample Table Chunk Offset atom
|
1047 |
+
if ($ParseAllPossibleAtoms) {
|
1048 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1049 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
1050 |
+
$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
|
1051 |
+
$stcoEntriesDataOffset = 8;
|
1052 |
for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
|
1053 |
+
$atom_structure['chunk_offset_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stcoEntriesDataOffset, 4));
|
1054 |
+
$stcoEntriesDataOffset += 4;
|
1055 |
}
|
1056 |
}
|
1057 |
+
break;
|
|
|
1058 |
|
1059 |
|
1060 |
+
case 'co64': // Chunk Offset 64-bit (version of "stco" that supports > 2GB files)
|
1061 |
+
if ($ParseAllPossibleAtoms) {
|
1062 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1063 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
1064 |
+
$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
|
1065 |
+
$stcoEntriesDataOffset = 8;
|
1066 |
+
for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
|
1067 |
+
$atom_structure['chunk_offset_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stcoEntriesDataOffset, 8));
|
1068 |
+
$stcoEntriesDataOffset += 8;
|
1069 |
+
}
|
1070 |
}
|
1071 |
+
break;
|
|
|
1072 |
|
1073 |
|
1074 |
+
case 'dref': // Data REFerence atom
|
|
|
1075 |
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1076 |
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
1077 |
$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
|
1078 |
+
$drefDataOffset = 8;
|
1079 |
for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
|
1080 |
+
$atom_structure['data_references'][$i]['size'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 4));
|
1081 |
+
$drefDataOffset += 4;
|
1082 |
+
$atom_structure['data_references'][$i]['type'] = substr($atom_data, $drefDataOffset, 4);
|
1083 |
+
$drefDataOffset += 4;
|
1084 |
+
$atom_structure['data_references'][$i]['version'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 1));
|
1085 |
+
$drefDataOffset += 1;
|
1086 |
+
$atom_structure['data_references'][$i]['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 3)); // hardcoded: 0x0000
|
1087 |
+
$drefDataOffset += 3;
|
1088 |
+
$atom_structure['data_references'][$i]['data'] = substr($atom_data, $drefDataOffset, ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3));
|
1089 |
+
$drefDataOffset += ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3);
|
1090 |
+
|
1091 |
+
$atom_structure['data_references'][$i]['flags']['self_reference'] = (bool) ($atom_structure['data_references'][$i]['flags_raw'] & 0x001);
|
1092 |
}
|
1093 |
+
break;
|
|
|
1094 |
|
1095 |
|
1096 |
+
case 'gmin': // base Media INformation atom
|
1097 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1098 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
1099 |
+
$atom_structure['graphics_mode'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2));
|
1100 |
+
$atom_structure['opcolor_red'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2));
|
1101 |
+
$atom_structure['opcolor_green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 2));
|
1102 |
+
$atom_structure['opcolor_blue'] = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2));
|
1103 |
+
$atom_structure['balance'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 2));
|
1104 |
+
$atom_structure['reserved'] = getid3_lib::BigEndian2Int(substr($atom_data, 14, 2));
|
1105 |
+
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1106 |
|
1107 |
|
1108 |
+
case 'smhd': // Sound Media information HeaDer atom
|
1109 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1110 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
1111 |
+
$atom_structure['balance'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2));
|
1112 |
+
$atom_structure['reserved'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2));
|
1113 |
+
break;
|
|
|
|
|
|
|
|
|
1114 |
|
1115 |
|
1116 |
+
case 'vmhd': // Video Media information HeaDer atom
|
1117 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1118 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
|
1119 |
+
$atom_structure['graphics_mode'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2));
|
1120 |
+
$atom_structure['opcolor_red'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2));
|
1121 |
+
$atom_structure['opcolor_green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 2));
|
1122 |
+
$atom_structure['opcolor_blue'] = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2));
|
1123 |
|
1124 |
+
$atom_structure['flags']['no_lean_ahead'] = (bool) ($atom_structure['flags_raw'] & 0x001);
|
1125 |
+
break;
|
1126 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1127 |
|
1128 |
+
case 'hdlr': // HanDLeR reference atom
|
1129 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1130 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
1131 |
+
$atom_structure['component_type'] = substr($atom_data, 4, 4);
|
1132 |
+
$atom_structure['component_subtype'] = substr($atom_data, 8, 4);
|
1133 |
+
$atom_structure['component_manufacturer'] = substr($atom_data, 12, 4);
|
1134 |
+
$atom_structure['component_flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
|
1135 |
+
$atom_structure['component_flags_mask'] = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4));
|
1136 |
+
$atom_structure['component_name'] = $this->Pascal2String(substr($atom_data, 24));
|
1137 |
|
1138 |
+
if (($atom_structure['component_subtype'] == 'STpn') && ($atom_structure['component_manufacturer'] == 'zzzz')) {
|
1139 |
+
$info['video']['dataformat'] = 'quicktimevr';
|
1140 |
+
}
|
1141 |
+
break;
|
1142 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1143 |
|
1144 |
+
case 'mdhd': // MeDia HeaDer atom
|
1145 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1146 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
1147 |
+
$atom_structure['creation_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
|
1148 |
+
$atom_structure['modify_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4));
|
1149 |
+
$atom_structure['time_scale'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
|
1150 |
+
$atom_structure['duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
|
1151 |
+
$atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 20, 2));
|
1152 |
+
$atom_structure['quality'] = getid3_lib::BigEndian2Int(substr($atom_data, 22, 2));
|
1153 |
|
1154 |
+
if ($atom_structure['time_scale'] == 0) {
|
1155 |
+
$this->error('Corrupt Quicktime file: mdhd.time_scale == zero');
|
1156 |
+
return false;
|
1157 |
+
}
|
1158 |
+
$info['quicktime']['time_scale'] = ((isset($info['quicktime']['time_scale']) && ($info['quicktime']['time_scale'] < 1000)) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);
|
1159 |
|
1160 |
+
$atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
|
1161 |
+
$atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
|
1162 |
+
$atom_structure['playtime_seconds'] = $atom_structure['duration'] / $atom_structure['time_scale'];
|
1163 |
+
$atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']);
|
1164 |
+
if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) {
|
1165 |
+
$info['comments']['language'][] = $atom_structure['language'];
|
1166 |
+
}
|
1167 |
+
break;
|
|
|
1168 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1169 |
|
1170 |
+
case 'pnot': // Preview atom
|
1171 |
+
$atom_structure['modification_date'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); // "standard Macintosh format"
|
1172 |
+
$atom_structure['version_number'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x00
|
1173 |
+
$atom_structure['atom_type'] = substr($atom_data, 6, 4); // usually: 'PICT'
|
1174 |
+
$atom_structure['atom_index'] = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2)); // usually: 0x01
|
1175 |
|
1176 |
+
$atom_structure['modification_date_unix'] = getid3_lib::DateMac2Unix($atom_structure['modification_date']);
|
1177 |
+
break;
|
|
|
|
|
|
|
1178 |
|
|
|
|
|
1179 |
|
1180 |
+
case 'crgn': // Clipping ReGioN atom
|
1181 |
+
$atom_structure['region_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); // The Region size, Region boundary box,
|
1182 |
+
$atom_structure['boundary_box'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 8)); // and Clipping region data fields
|
1183 |
+
$atom_structure['clipping_data'] = substr($atom_data, 10); // constitute a QuickDraw region.
|
1184 |
+
break;
|
1185 |
|
|
|
|
|
|
|
|
|
|
|
1186 |
|
1187 |
+
case 'load': // track LOAD settings atom
|
1188 |
+
$atom_structure['preload_start_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
|
1189 |
+
$atom_structure['preload_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
|
1190 |
+
$atom_structure['preload_flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4));
|
1191 |
+
$atom_structure['default_hints_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
|
1192 |
|
1193 |
+
$atom_structure['default_hints']['double_buffer'] = (bool) ($atom_structure['default_hints_raw'] & 0x0020);
|
1194 |
+
$atom_structure['default_hints']['high_quality'] = (bool) ($atom_structure['default_hints_raw'] & 0x0100);
|
1195 |
+
break;
|
|
|
|
|
1196 |
|
|
|
|
|
|
|
1197 |
|
1198 |
+
case 'tmcd': // TiMe CoDe atom
|
1199 |
+
case 'chap': // CHAPter list atom
|
1200 |
+
case 'sync': // SYNChronization atom
|
1201 |
+
case 'scpt': // tranSCriPT atom
|
1202 |
+
case 'ssrc': // non-primary SouRCe atom
|
1203 |
+
for ($i = 0; $i < strlen($atom_data); $i += 4) {
|
1204 |
+
@$atom_structure['track_id'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4));
|
1205 |
+
}
|
1206 |
+
break;
|
1207 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1208 |
|
1209 |
+
case 'elst': // Edit LiST atom
|
1210 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1211 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
1212 |
+
$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
|
1213 |
+
for ($i = 0; $i < $atom_structure['number_entries']; $i++ ) {
|
1214 |
+
$atom_structure['edit_list'][$i]['track_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 0, 4));
|
1215 |
+
$atom_structure['edit_list'][$i]['media_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 4, 4));
|
1216 |
+
$atom_structure['edit_list'][$i]['media_rate'] = getid3_lib::FixedPoint16_16(substr($atom_data, 8 + ($i * 12) + 8, 4));
|
1217 |
+
}
|
1218 |
+
break;
|
1219 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1220 |
|
1221 |
+
case 'kmat': // compressed MATte atom
|
1222 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1223 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
|
1224 |
+
$atom_structure['matte_data_raw'] = substr($atom_data, 4);
|
1225 |
+
break;
|
1226 |
|
|
|
|
|
|
|
|
|
|
|
1227 |
|
1228 |
+
case 'ctab': // Color TABle atom
|
1229 |
+
$atom_structure['color_table_seed'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); // hardcoded: 0x00000000
|
1230 |
+
$atom_structure['color_table_flags'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x8000
|
1231 |
+
$atom_structure['color_table_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2)) + 1;
|
1232 |
+
for ($colortableentry = 0; $colortableentry < $atom_structure['color_table_size']; $colortableentry++) {
|
1233 |
+
$atom_structure['color_table'][$colortableentry]['alpha'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 0, 2));
|
1234 |
+
$atom_structure['color_table'][$colortableentry]['red'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 2, 2));
|
1235 |
+
$atom_structure['color_table'][$colortableentry]['green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 4, 2));
|
1236 |
+
$atom_structure['color_table'][$colortableentry]['blue'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 6, 2));
|
1237 |
+
}
|
1238 |
+
break;
|
1239 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1240 |
|
1241 |
+
case 'mvhd': // MoVie HeaDer atom
|
1242 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1243 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
|
1244 |
+
$atom_structure['creation_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
|
1245 |
+
$atom_structure['modify_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4));
|
1246 |
+
$atom_structure['time_scale'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
|
1247 |
+
$atom_structure['duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
|
1248 |
+
$atom_structure['preferred_rate'] = getid3_lib::FixedPoint16_16(substr($atom_data, 20, 4));
|
1249 |
+
$atom_structure['preferred_volume'] = getid3_lib::FixedPoint8_8(substr($atom_data, 24, 2));
|
1250 |
+
$atom_structure['reserved'] = substr($atom_data, 26, 10);
|
1251 |
+
$atom_structure['matrix_a'] = getid3_lib::FixedPoint16_16(substr($atom_data, 36, 4));
|
1252 |
+
$atom_structure['matrix_b'] = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4));
|
1253 |
+
$atom_structure['matrix_u'] = getid3_lib::FixedPoint2_30(substr($atom_data, 44, 4));
|
1254 |
+
$atom_structure['matrix_c'] = getid3_lib::FixedPoint16_16(substr($atom_data, 48, 4));
|
1255 |
+
$atom_structure['matrix_d'] = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4));
|
1256 |
+
$atom_structure['matrix_v'] = getid3_lib::FixedPoint2_30(substr($atom_data, 56, 4));
|
1257 |
+
$atom_structure['matrix_x'] = getid3_lib::FixedPoint16_16(substr($atom_data, 60, 4));
|
1258 |
+
$atom_structure['matrix_y'] = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4));
|
1259 |
+
$atom_structure['matrix_w'] = getid3_lib::FixedPoint2_30(substr($atom_data, 68, 4));
|
1260 |
+
$atom_structure['preview_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 72, 4));
|
1261 |
+
$atom_structure['preview_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 76, 4));
|
1262 |
+
$atom_structure['poster_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 80, 4));
|
1263 |
+
$atom_structure['selection_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 84, 4));
|
1264 |
+
$atom_structure['selection_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 88, 4));
|
1265 |
+
$atom_structure['current_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 92, 4));
|
1266 |
+
$atom_structure['next_track_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 96, 4));
|
1267 |
+
|
1268 |
+
if ($atom_structure['time_scale'] == 0) {
|
1269 |
+
$this->error('Corrupt Quicktime file: mvhd.time_scale == zero');
|
1270 |
+
return false;
|
1271 |
+
}
|
1272 |
+
$atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
|
1273 |
+
$atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
|
1274 |
+
$info['quicktime']['time_scale'] = ((isset($info['quicktime']['time_scale']) && ($info['quicktime']['time_scale'] < 1000)) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);
|
1275 |
+
$info['quicktime']['display_scale'] = $atom_structure['matrix_a'];
|
1276 |
+
$info['playtime_seconds'] = $atom_structure['duration'] / $atom_structure['time_scale'];
|
1277 |
+
break;
|
1278 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1279 |
|
1280 |
+
case 'tkhd': // TracK HeaDer atom
|
1281 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1282 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
|
1283 |
+
$atom_structure['creation_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
|
1284 |
+
$atom_structure['modify_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4));
|
1285 |
+
$atom_structure['trackid'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
|
1286 |
+
$atom_structure['reserved1'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
|
1287 |
+
$atom_structure['duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4));
|
1288 |
+
$atom_structure['reserved2'] = getid3_lib::BigEndian2Int(substr($atom_data, 24, 8));
|
1289 |
+
$atom_structure['layer'] = getid3_lib::BigEndian2Int(substr($atom_data, 32, 2));
|
1290 |
+
$atom_structure['alternate_group'] = getid3_lib::BigEndian2Int(substr($atom_data, 34, 2));
|
1291 |
+
$atom_structure['volume'] = getid3_lib::FixedPoint8_8(substr($atom_data, 36, 2));
|
1292 |
+
$atom_structure['reserved3'] = getid3_lib::BigEndian2Int(substr($atom_data, 38, 2));
|
1293 |
+
// http://developer.apple.com/library/mac/#documentation/QuickTime/RM/MovieBasics/MTEditing/K-Chapter/11MatrixFunctions.html
|
1294 |
+
// http://developer.apple.com/library/mac/#documentation/QuickTime/qtff/QTFFChap4/qtff4.html#//apple_ref/doc/uid/TP40000939-CH206-18737
|
1295 |
+
$atom_structure['matrix_a'] = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4));
|
1296 |
+
$atom_structure['matrix_b'] = getid3_lib::FixedPoint16_16(substr($atom_data, 44, 4));
|
1297 |
+
$atom_structure['matrix_u'] = getid3_lib::FixedPoint2_30(substr($atom_data, 48, 4));
|
1298 |
+
$atom_structure['matrix_c'] = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4));
|
1299 |
+
$atom_structure['matrix_d'] = getid3_lib::FixedPoint16_16(substr($atom_data, 56, 4));
|
1300 |
+
$atom_structure['matrix_v'] = getid3_lib::FixedPoint2_30(substr($atom_data, 60, 4));
|
1301 |
+
$atom_structure['matrix_x'] = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4));
|
1302 |
+
$atom_structure['matrix_y'] = getid3_lib::FixedPoint16_16(substr($atom_data, 68, 4));
|
1303 |
+
$atom_structure['matrix_w'] = getid3_lib::FixedPoint2_30(substr($atom_data, 72, 4));
|
1304 |
+
$atom_structure['width'] = getid3_lib::FixedPoint16_16(substr($atom_data, 76, 4));
|
1305 |
+
$atom_structure['height'] = getid3_lib::FixedPoint16_16(substr($atom_data, 80, 4));
|
1306 |
+
$atom_structure['flags']['enabled'] = (bool) ($atom_structure['flags_raw'] & 0x0001);
|
1307 |
+
$atom_structure['flags']['in_movie'] = (bool) ($atom_structure['flags_raw'] & 0x0002);
|
1308 |
+
$atom_structure['flags']['in_preview'] = (bool) ($atom_structure['flags_raw'] & 0x0004);
|
1309 |
+
$atom_structure['flags']['in_poster'] = (bool) ($atom_structure['flags_raw'] & 0x0008);
|
1310 |
+
$atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
|
1311 |
+
$atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
|
1312 |
+
|
1313 |
+
// https://www.getid3.org/phpBB3/viewtopic.php?t=1908
|
1314 |
+
// attempt to compute rotation from matrix values
|
1315 |
+
// 2017-Dec-28: uncertain if 90/270 are correctly oriented; values returned by FixedPoint16_16 should perhaps be -1 instead of 65535(?)
|
1316 |
+
$matrixRotation = 0;
|
1317 |
+
switch ($atom_structure['matrix_a'].':'.$atom_structure['matrix_b'].':'.$atom_structure['matrix_c'].':'.$atom_structure['matrix_d']) {
|
1318 |
+
case '1:0:0:1': $matrixRotation = 0; break;
|
1319 |
+
case '0:1:65535:0': $matrixRotation = 90; break;
|
1320 |
+
case '65535:0:0:65535': $matrixRotation = 180; break;
|
1321 |
+
case '0:65535:1:0': $matrixRotation = 270; break;
|
1322 |
+
default: break;
|
1323 |
+
}
|
1324 |
|
1325 |
+
// https://www.getid3.org/phpBB3/viewtopic.php?t=2468
|
1326 |
+
// The rotation matrix can appear in the Quicktime file multiple times, at least once for each track,
|
1327 |
+
// and it's possible that only the video track (or, in theory, one of the video tracks) is flagged as
|
1328 |
+
// rotated while the other tracks (e.g. audio) is tagged as rotation=0 (behavior noted on iPhone 8 Plus)
|
1329 |
+
// The correct solution would be to check if the TrackID associated with the rotation matrix is indeed
|
1330 |
+
// a video track (or the main video track) and only set the rotation then, but since information about
|
1331 |
+
// what track is what is not trivially there to be examined, the lazy solution is to set the rotation
|
1332 |
+
// if it is found to be nonzero, on the assumption that tracks that don't need it will have rotation set
|
1333 |
+
// to zero (and be effectively ignored) and the video track will have rotation set correctly, which will
|
1334 |
+
// either be zero and automatically correct, or nonzero and be set correctly.
|
1335 |
+
if (!isset($info['video']['rotate']) || (($info['video']['rotate'] == 0) && ($matrixRotation > 0))) {
|
1336 |
+
$info['quicktime']['video']['rotate'] = $info['video']['rotate'] = $matrixRotation;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1337 |
}
|
1338 |
+
|
1339 |
+
if ($atom_structure['flags']['enabled'] == 1) {
|
1340 |
+
if (!isset($info['video']['resolution_x']) || !isset($info['video']['resolution_y'])) {
|
1341 |
+
$info['video']['resolution_x'] = $atom_structure['width'];
|
1342 |
+
$info['video']['resolution_y'] = $atom_structure['height'];
|
1343 |
+
}
|
1344 |
+
$info['video']['resolution_x'] = max($info['video']['resolution_x'], $atom_structure['width']);
|
1345 |
+
$info['video']['resolution_y'] = max($info['video']['resolution_y'], $atom_structure['height']);
|
1346 |
+
$info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x'];
|
1347 |
+
$info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y'];
|
1348 |
+
} else {
|
1349 |
+
// see: https://www.getid3.org/phpBB3/viewtopic.php?t=1295
|
1350 |
+
//if (isset($info['video']['resolution_x'])) { unset($info['video']['resolution_x']); }
|
1351 |
+
//if (isset($info['video']['resolution_y'])) { unset($info['video']['resolution_y']); }
|
1352 |
+
//if (isset($info['quicktime']['video'])) { unset($info['quicktime']['video']); }
|
1353 |
+
}
|
1354 |
+
break;
|
1355 |
|
1356 |
|
1357 |
+
case 'iods': // Initial Object DeScriptor atom
|
1358 |
+
// http://www.koders.com/c/fid1FAB3E762903DC482D8A246D4A4BF9F28E049594.aspx?s=windows.h
|
1359 |
+
// http://libquicktime.sourcearchive.com/documentation/1.0.2plus-pdebian/iods_8c-source.html
|
1360 |
+
$offset = 0;
|
1361 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
|
1362 |
+
$offset += 1;
|
1363 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 3));
|
1364 |
+
$offset += 3;
|
1365 |
+
$atom_structure['mp4_iod_tag'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1366 |
$offset += 1;
|
1367 |
+
$atom_structure['length'] = $this->quicktime_read_mp4_descr_length($atom_data, $offset);
|
1368 |
//$offset already adjusted by quicktime_read_mp4_descr_length()
|
1369 |
+
$atom_structure['object_descriptor_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2));
|
1370 |
+
$offset += 2;
|
1371 |
+
$atom_structure['od_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
|
1372 |
+
$offset += 1;
|
1373 |
+
$atom_structure['scene_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
|
1374 |
+
$offset += 1;
|
1375 |
+
$atom_structure['audio_profile_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
|
1376 |
+
$offset += 1;
|
1377 |
+
$atom_structure['video_profile_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
|
1378 |
+
$offset += 1;
|
1379 |
+
$atom_structure['graphics_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
|
1380 |
+
$offset += 1;
|
1381 |
|
1382 |
+
$atom_structure['num_iods_tracks'] = ($atom_structure['length'] - 7) / 6; // 6 bytes would only be right if all tracks use 1-byte length fields
|
1383 |
+
for ($i = 0; $i < $atom_structure['num_iods_tracks']; $i++) {
|
1384 |
+
$atom_structure['track'][$i]['ES_ID_IncTag'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
|
1385 |
+
$offset += 1;
|
1386 |
+
$atom_structure['track'][$i]['length'] = $this->quicktime_read_mp4_descr_length($atom_data, $offset);
|
1387 |
+
//$offset already adjusted by quicktime_read_mp4_descr_length()
|
1388 |
+
$atom_structure['track'][$i]['track_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 4));
|
1389 |
+
$offset += 4;
|
1390 |
+
}
|
1391 |
|
1392 |
+
$atom_structure['audio_profile_name'] = $this->QuicktimeIODSaudioProfileName($atom_structure['audio_profile_id']);
|
1393 |
+
$atom_structure['video_profile_name'] = $this->QuicktimeIODSvideoProfileName($atom_structure['video_profile_id']);
|
1394 |
+
break;
|
1395 |
+
|
1396 |
+
case 'ftyp': // FileTYPe (?) atom (for MP4 it seems)
|
1397 |
+
$atom_structure['signature'] = substr($atom_data, 0, 4);
|
1398 |
+
$atom_structure['unknown_1'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
|
1399 |
+
$atom_structure['fourcc'] = substr($atom_data, 8, 4);
|
1400 |
+
break;
|
1401 |
|
1402 |
+
case 'mdat': // Media DATa atom
|
1403 |
+
// 'mdat' contains the actual data for the audio/video, possibly also subtitles
|
1404 |
|
1405 |
+
/* due to lack of known documentation, this is a kludge implementation. If you know of documentation on how mdat is properly structed, please send it to info@getid3.org */
|
1406 |
|
1407 |
+
// first, skip any 'wide' padding, and second 'mdat' header (with specified size of zero?)
|
1408 |
+
$mdat_offset = 0;
|
1409 |
+
while (true) {
|
1410 |
+
if (substr($atom_data, $mdat_offset, 8) == "\x00\x00\x00\x08".'wide') {
|
1411 |
+
$mdat_offset += 8;
|
1412 |
+
} elseif (substr($atom_data, $mdat_offset, 8) == "\x00\x00\x00\x00".'mdat') {
|
1413 |
+
$mdat_offset += 8;
|
1414 |
+
} else {
|
1415 |
+
break;
|
1416 |
+
}
|
1417 |
+
}
|
1418 |
+
if (substr($atom_data, $mdat_offset, 4) == 'GPRO') {
|
1419 |
+
$GOPRO_chunk_length = getid3_lib::LittleEndian2Int(substr($atom_data, $mdat_offset + 4, 4));
|
1420 |
+
$GOPRO_offset = 8;
|
1421 |
+
$atom_structure['GPRO']['raw'] = substr($atom_data, $mdat_offset + 8, $GOPRO_chunk_length - 8);
|
1422 |
+
$atom_structure['GPRO']['firmware'] = substr($atom_structure['GPRO']['raw'], 0, 15);
|
1423 |
+
$atom_structure['GPRO']['unknown1'] = substr($atom_structure['GPRO']['raw'], 15, 16);
|
1424 |
+
$atom_structure['GPRO']['unknown2'] = substr($atom_structure['GPRO']['raw'], 31, 32);
|
1425 |
+
$atom_structure['GPRO']['unknown3'] = substr($atom_structure['GPRO']['raw'], 63, 16);
|
1426 |
+
$atom_structure['GPRO']['camera'] = substr($atom_structure['GPRO']['raw'], 79, 32);
|
1427 |
+
$info['quicktime']['camera']['model'] = rtrim($atom_structure['GPRO']['camera'], "\x00");
|
1428 |
}
|
|
|
1429 |
|
1430 |
+
// check to see if it looks like chapter titles, in the form of unterminated strings with a leading 16-bit size field
|
1431 |
+
while (($mdat_offset < (strlen($atom_data) - 8))
|
1432 |
+
&& ($chapter_string_length = getid3_lib::BigEndian2Int(substr($atom_data, $mdat_offset, 2)))
|
1433 |
+
&& ($chapter_string_length < 1000)
|
1434 |
+
&& ($chapter_string_length <= (strlen($atom_data) - $mdat_offset - 2))
|
1435 |
+
&& preg_match('#^([\x00-\xFF]{2})([\x20-\xFF]+)$#', substr($atom_data, $mdat_offset, $chapter_string_length + 2), $chapter_matches)) {
|
1436 |
+
list($dummy, $chapter_string_length_hex, $chapter_string) = $chapter_matches;
|
1437 |
+
$mdat_offset += (2 + $chapter_string_length);
|
1438 |
+
@$info['quicktime']['comments']['chapters'][] = $chapter_string;
|
1439 |
+
|
1440 |
+
// "encd" atom specifies encoding. In theory could be anything, almost always UTF-8, but may be UTF-16 with BOM (not currently handled)
|
1441 |
+
if (substr($atom_data, $mdat_offset, 12) == "\x00\x00\x00\x0C\x65\x6E\x63\x64\x00\x00\x01\x00") { // UTF-8
|
1442 |
+
$mdat_offset += 12;
|
1443 |
+
}
|
1444 |
+
}
|
1445 |
|
1446 |
+
if (($atomsize > 8) && (!isset($info['avdataend_tmp']) || ($info['quicktime'][$atomname]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) {
|
1447 |
+
|
1448 |
+
$info['avdataoffset'] = $atom_structure['offset'] + 8; // $info['quicktime'][$atomname]['offset'] + 8;
|
1449 |
+
$OldAVDataEnd = $info['avdataend'];
|
1450 |
+
$info['avdataend'] = $atom_structure['offset'] + $atom_structure['size']; // $info['quicktime'][$atomname]['offset'] + $info['quicktime'][$atomname]['size'];
|
1451 |
+
|
1452 |
+
$getid3_temp = new getID3();
|
1453 |
+
$getid3_temp->openfile($this->getid3->filename);
|
1454 |
+
$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
|
1455 |
+
$getid3_temp->info['avdataend'] = $info['avdataend'];
|
1456 |
+
$getid3_mp3 = new getid3_mp3($getid3_temp);
|
1457 |
+
if ($getid3_mp3->MPEGaudioHeaderValid($getid3_mp3->MPEGaudioHeaderDecode($this->fread(4)))) {
|
1458 |
+
$getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false);
|
1459 |
+
if (!empty($getid3_temp->info['warning'])) {
|
1460 |
+
foreach ($getid3_temp->info['warning'] as $value) {
|
1461 |
+
$this->warning($value);
|
1462 |
+
}
|
1463 |
+
}
|
1464 |
+
if (!empty($getid3_temp->info['mpeg'])) {
|
1465 |
+
$info['mpeg'] = $getid3_temp->info['mpeg'];
|
1466 |
+
if (isset($info['mpeg']['audio'])) {
|
1467 |
+
$info['audio']['dataformat'] = 'mp3';
|
1468 |
+
$info['audio']['codec'] = (!empty($info['mpeg']['audio']['encoder']) ? $info['mpeg']['audio']['encoder'] : (!empty($info['mpeg']['audio']['codec']) ? $info['mpeg']['audio']['codec'] : (!empty($info['mpeg']['audio']['LAME']) ? 'LAME' :'mp3')));
|
1469 |
+
$info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate'];
|
1470 |
+
$info['audio']['channels'] = $info['mpeg']['audio']['channels'];
|
1471 |
+
$info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate'];
|
1472 |
+
$info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
|
1473 |
+
$info['bitrate'] = $info['audio']['bitrate'];
|
1474 |
+
}
|
1475 |
+
}
|
1476 |
+
}
|
1477 |
+
unset($getid3_mp3, $getid3_temp);
|
1478 |
+
$info['avdataend'] = $OldAVDataEnd;
|
1479 |
+
unset($OldAVDataEnd);
|
1480 |
|
1481 |
+
}
|
1482 |
|
1483 |
+
unset($mdat_offset, $chapter_string_length, $chapter_matches);
|
1484 |
+
break;
|
1485 |
|
1486 |
+
case 'free': // FREE space atom
|
1487 |
+
case 'skip': // SKIP atom
|
1488 |
+
case 'wide': // 64-bit expansion placeholder atom
|
1489 |
+
// 'free', 'skip' and 'wide' are just padding, contains no useful data at all
|
1490 |
+
|
1491 |
+
// When writing QuickTime files, it is sometimes necessary to update an atom's size.
|
1492 |
+
// It is impossible to update a 32-bit atom to a 64-bit atom since the 32-bit atom
|
1493 |
+
// is only 8 bytes in size, and the 64-bit atom requires 16 bytes. Therefore, QuickTime
|
1494 |
+
// puts an 8-byte placeholder atom before any atoms it may have to update the size of.
|
1495 |
+
// In this way, if the atom needs to be converted from a 32-bit to a 64-bit atom, the
|
1496 |
+
// placeholder atom can be overwritten to obtain the necessary 8 extra bytes.
|
1497 |
+
// The placeholder atom has a type of kWideAtomPlaceholderType ( 'wide' ).
|
1498 |
+
break;
|
1499 |
|
1500 |
+
|
1501 |
+
case 'nsav': // NoSAVe atom
|
1502 |
+
// http://developer.apple.com/technotes/tn/tn2038.html
|
1503 |
+
$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
|
1504 |
+
break;
|
1505 |
+
|
1506 |
+
case 'ctyp': // Controller TYPe atom (seen on QTVR)
|
1507 |
+
// http://homepages.slingshot.co.nz/~helmboy/quicktime/formats/qtm-layout.txt
|
1508 |
+
// some controller names are:
|
1509 |
+
// 0x00 + 'std' for linear movie
|
1510 |
+
// 'none' for no controls
|
1511 |
+
$atom_structure['ctyp'] = substr($atom_data, 0, 4);
|
1512 |
+
$info['quicktime']['controller'] = $atom_structure['ctyp'];
|
1513 |
+
switch ($atom_structure['ctyp']) {
|
1514 |
+
case 'qtvr':
|
1515 |
+
$info['video']['dataformat'] = 'quicktimevr';
|
1516 |
+
break;
|
1517 |
+
}
|
1518 |
+
break;
|
1519 |
+
|
1520 |
+
case 'pano': // PANOrama track (seen on QTVR)
|
1521 |
+
$atom_structure['pano'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
|
1522 |
+
break;
|
1523 |
+
|
1524 |
+
case 'hint': // HINT track
|
1525 |
+
case 'hinf': //
|
1526 |
+
case 'hinv': //
|
1527 |
+
case 'hnti': //
|
1528 |
+
$info['quicktime']['hinting'] = true;
|
1529 |
+
break;
|
1530 |
+
|
1531 |
+
case 'imgt': // IMaGe Track reference (kQTVRImageTrackRefType) (seen on QTVR)
|
1532 |
+
for ($i = 0; $i < ($atom_structure['size'] - 8); $i += 4) {
|
1533 |
+
$atom_structure['imgt'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4));
|
1534 |
+
}
|
1535 |
+
break;
|
1536 |
+
|
1537 |
+
|
1538 |
+
// Observed-but-not-handled atom types are just listed here to prevent warnings being generated
|
1539 |
+
case 'FXTC': // Something to do with Adobe After Effects (?)
|
1540 |
+
case 'PrmA':
|
1541 |
+
case 'code':
|
1542 |
+
case 'FIEL': // this is NOT "fiel" (Field Ordering) as describe here: http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap3/chapter_4_section_2.html
|
1543 |
+
case 'tapt': // TrackApertureModeDimensionsAID - http://developer.apple.com/documentation/QuickTime/Reference/QT7-1_Update_Reference/Constants/Constants.html
|
1544 |
+
// tapt seems to be used to compute the video size [https://www.getid3.org/phpBB3/viewtopic.php?t=838]
|
1545 |
+
// * http://lists.apple.com/archives/quicktime-api/2006/Aug/msg00014.html
|
1546 |
+
// * http://handbrake.fr/irclogs/handbrake-dev/handbrake-dev20080128_pg2.html
|
1547 |
+
case 'ctts':// STCompositionOffsetAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
|
1548 |
+
case 'cslg':// STCompositionShiftLeastGreatestAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
|
1549 |
+
case 'sdtp':// STSampleDependencyAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
|
1550 |
+
case 'stps':// STPartialSyncSampleAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
|
1551 |
+
//$atom_structure['data'] = $atom_data;
|
1552 |
+
break;
|
1553 |
+
|
1554 |
+
case "\xA9".'xyz': // GPS latitude+longitude+altitude
|
1555 |
+
$atom_structure['data'] = $atom_data;
|
1556 |
+
if (preg_match('#([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)?/$#i', $atom_data, $matches)) {
|
1557 |
+
@list($all, $latitude, $longitude, $altitude) = $matches;
|
1558 |
+
$info['quicktime']['comments']['gps_latitude'][] = floatval($latitude);
|
1559 |
+
$info['quicktime']['comments']['gps_longitude'][] = floatval($longitude);
|
1560 |
+
if (!empty($altitude)) {
|
1561 |
+
$info['quicktime']['comments']['gps_altitude'][] = floatval($altitude);
|
1562 |
}
|
1563 |
+
} else {
|
1564 |
+
$this->warning('QuickTime atom "©xyz" data does not match expected data pattern at offset '.$baseoffset.'. Please report as getID3() bug.');
|
1565 |
}
|
1566 |
+
break;
|
|
|
|
|
1567 |
|
1568 |
+
case 'NCDT':
|
1569 |
+
// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
|
1570 |
+
// Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from some Nikon cameras such as the Coolpix S8000 and D5100
|
1571 |
+
$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 4, $atomHierarchy, $ParseAllPossibleAtoms);
|
1572 |
+
break;
|
1573 |
+
case 'NCTH': // Nikon Camera THumbnail image
|
1574 |
+
case 'NCVW': // Nikon Camera preVieW image
|
1575 |
+
// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
|
1576 |
+
if (preg_match('/^\xFF\xD8\xFF/', $atom_data)) {
|
1577 |
+
$atom_structure['data'] = $atom_data;
|
1578 |
+
$atom_structure['image_mime'] = 'image/jpeg';
|
1579 |
+
$atom_structure['description'] = (($atomname == 'NCTH') ? 'Nikon Camera Thumbnail Image' : (($atomname == 'NCVW') ? 'Nikon Camera Preview Image' : 'Nikon preview image'));
|
1580 |
+
$info['quicktime']['comments']['picture'][] = array('image_mime'=>$atom_structure['image_mime'], 'data'=>$atom_data, 'description'=>$atom_structure['description']);
|
1581 |
+
}
|
1582 |
+
break;
|
1583 |
+
case 'NCTG': // Nikon - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG
|
1584 |
+
$atom_structure['data'] = $this->QuicktimeParseNikonNCTG($atom_data);
|
1585 |
+
break;
|
1586 |
+
case 'NCHD': // Nikon:MakerNoteVersion - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
|
1587 |
+
case 'NCDB': // Nikon - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
|
1588 |
+
case 'CNCV': // Canon:CompressorVersion - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html
|
1589 |
+
$atom_structure['data'] = $atom_data;
|
1590 |
+
break;
|
1591 |
|
1592 |
+
case "\x00\x00\x00\x00":
|
1593 |
+
// some kind of metacontainer, may contain a big data dump such as:
|
1594 |
+
// mdta keys \005 mdtacom.apple.quicktime.make (mdtacom.apple.quicktime.creationdate ,mdtacom.apple.quicktime.location.ISO6709 $mdtacom.apple.quicktime.software !mdtacom.apple.quicktime.model ilst \01D \001 \015data \001DE\010Apple 0 \002 (data \001DE\0102011-05-11T17:54:04+0200 2 \003 *data \001DE\010+52.4936+013.3897+040.247/ \01D \004 \015data \001DE\0104.3.1 \005 \018data \001DE\010iPhone 4
|
1595 |
+
// http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt
|
1596 |
|
1597 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1598 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
|
1599 |
+
$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom(substr($atom_data, 4), $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
|
1600 |
+
//$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
|
1601 |
+
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1602 |
|
1603 |
+
case 'meta': // METAdata atom
|
1604 |
+
// https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
|
1605 |
|
1606 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1607 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
|
1608 |
+
$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
|
1609 |
+
break;
|
1610 |
|
1611 |
+
case 'data': // metaDATA atom
|
1612 |
+
static $metaDATAkey = 1; // real ugly, but so is the QuickTime structure that stores keys and values in different multinested locations that are hard to relate to each other
|
1613 |
+
// seems to be 2 bytes language code (ASCII), 2 bytes unknown (set to 0x10B5 in sample I have), remainder is useful data
|
1614 |
+
$atom_structure['language'] = substr($atom_data, 4 + 0, 2);
|
1615 |
+
$atom_structure['unknown'] = getid3_lib::BigEndian2Int(substr($atom_data, 4 + 2, 2));
|
1616 |
+
$atom_structure['data'] = substr($atom_data, 4 + 4);
|
1617 |
+
$atom_structure['key_name'] = @$info['quicktime']['temp_meta_key_names'][$metaDATAkey++];
|
|
|
|
|
|
|
|
|
|
|
|
|
1618 |
|
1619 |
+
if ($atom_structure['key_name'] && $atom_structure['data']) {
|
1620 |
+
@$info['quicktime']['comments'][str_replace('com.apple.quicktime.', '', $atom_structure['key_name'])][] = $atom_structure['data'];
|
1621 |
+
}
|
1622 |
+
break;
|
1623 |
|
1624 |
+
case 'keys': // KEYS that may be present in the metadata atom.
|
1625 |
+
// https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW21
|
1626 |
+
// The metadata item keys atom holds a list of the metadata keys that may be present in the metadata atom.
|
1627 |
+
// This list is indexed starting with 1; 0 is a reserved index value. The metadata item keys atom is a full atom with an atom type of "keys".
|
1628 |
+
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
1629 |
+
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
|
1630 |
+
$atom_structure['entry_count'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
|
1631 |
+
$keys_atom_offset = 8;
|
1632 |
+
for ($i = 1; $i <= $atom_structure['entry_count']; $i++) {
|
1633 |
+
$atom_structure['keys'][$i]['key_size'] = getid3_lib::BigEndian2Int(substr($atom_data, $keys_atom_offset + 0, 4));
|
1634 |
+
$atom_structure['keys'][$i]['key_namespace'] = substr($atom_data, $keys_atom_offset + 4, 4);
|
1635 |
+
$atom_structure['keys'][$i]['key_value'] = substr($atom_data, $keys_atom_offset + 8, $atom_structure['keys'][$i]['key_size'] - 8);
|
1636 |
+
$keys_atom_offset += $atom_structure['keys'][$i]['key_size']; // key_size includes the 4+4 bytes for key_size and key_namespace
|
1637 |
+
|
1638 |
+
$info['quicktime']['temp_meta_key_names'][$i] = $atom_structure['keys'][$i]['key_value'];
|
1639 |
+
}
|
1640 |
+
break;
|
1641 |
|
1642 |
+
case 'gps ':
|
1643 |
+
// https://dashcamtalk.com/forum/threads/script-to-extract-gps-data-from-novatek-mp4.20808/page-2#post-291730
|
1644 |
+
// The 'gps ' contains simple look up table made up of 8byte rows, that point to the 'free' atoms that contains the actual GPS data.
|
1645 |
+
// The first row is version/metadata/notsure, I skip that.
|
1646 |
+
// The following rows consist of 4byte address (absolute) and 4byte size (0x1000), these point to the GPS data in the file.
|
1647 |
+
|
1648 |
+
$GPS_rowsize = 8; // 4 bytes for offset, 4 bytes for size
|
1649 |
+
if (strlen($atom_data) > 0) {
|
1650 |
+
if ((strlen($atom_data) % $GPS_rowsize) == 0) {
|
1651 |
+
$atom_structure['gps_toc'] = array();
|
1652 |
+
foreach (str_split($atom_data, $GPS_rowsize) as $counter => $datapair) {
|
1653 |
+
$atom_structure['gps_toc'][] = unpack('Noffset/Nsize', substr($atom_data, $counter * $GPS_rowsize, $GPS_rowsize));
|
1654 |
+
}
|
1655 |
|
1656 |
+
$atom_structure['gps_entries'] = array();
|
1657 |
+
$previous_offset = $this->ftell();
|
1658 |
+
foreach ($atom_structure['gps_toc'] as $key => $gps_pointer) {
|
1659 |
+
if ($key == 0) {
|
1660 |
+
// "The first row is version/metadata/notsure, I skip that."
|
1661 |
+
continue;
|
1662 |
+
}
|
1663 |
+
$this->fseek($gps_pointer['offset']);
|
1664 |
+
$GPS_free_data = $this->fread($gps_pointer['size']);
|
1665 |
+
|
1666 |
+
/*
|
1667 |
+
// 2017-05-10: I see some of the data, notably the Hour-Minute-Second, but cannot reconcile the rest of the data. However, the NMEA "GPRMC" line is there and relatively easy to parse, so I'm using that instead
|
1668 |
+
|
1669 |
+
// https://dashcamtalk.com/forum/threads/script-to-extract-gps-data-from-novatek-mp4.20808/page-2#post-291730
|
1670 |
+
// The structure of the GPS data atom (the 'free' atoms mentioned above) is following:
|
1671 |
+
// hour,minute,second,year,month,day,active,latitude_b,longitude_b,unknown2,latitude,longitude,speed = struct.unpack_from('<IIIIIIssssfff',data, 48)
|
1672 |
+
// For those unfamiliar with python struct:
|
1673 |
+
// I = int
|
1674 |
+
// s = is string (size 1, in this case)
|
1675 |
+
// f = float
|
1676 |
+
|
1677 |
+
//$atom_structure['gps_entries'][$key] = unpack('Vhour/Vminute/Vsecond/Vyear/Vmonth/Vday/Vactive/Vlatitude_b/Vlongitude_b/Vunknown2/flatitude/flongitude/fspeed', substr($GPS_free_data, 48));
|
1678 |
+
*/
|
1679 |
+
|
1680 |
+
// $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62
|
1681 |
+
// $GPRMC,183731,A,3907.482,N,12102.436,W,000.0,360.0,080301,015.5,E*67
|
1682 |
+
// $GPRMC,002454,A,3553.5295,N,13938.6570,E,0.0,43.1,180700,7.1,W,A*3F
|
1683 |
+
// $GPRMC,094347.000,A,5342.0061,N,00737.9908,W,0.01,156.75,140217,,,A*7D
|
1684 |
+
if (preg_match('#\\$GPRMC,([0-9\\.]*),([AV]),([0-9\\.]*),([NS]),([0-9\\.]*),([EW]),([0-9\\.]*),([0-9\\.]*),([0-9]*),([0-9\\.]*),([EW]?)(,[A])?(\\*[0-9A-F]{2})#', $GPS_free_data, $matches)) {
|
1685 |
+
$GPS_this_GPRMC = array();
|
1686 |
+
list(
|
1687 |
+
$GPS_this_GPRMC['raw']['gprmc'],
|
1688 |
+
$GPS_this_GPRMC['raw']['timestamp'],
|
1689 |
+
$GPS_this_GPRMC['raw']['status'],
|
1690 |
+
$GPS_this_GPRMC['raw']['latitude'],
|
1691 |
+
$GPS_this_GPRMC['raw']['latitude_direction'],
|
1692 |
+
$GPS_this_GPRMC['raw']['longitude'],
|
1693 |
+
$GPS_this_GPRMC['raw']['longitude_direction'],
|
1694 |
+
$GPS_this_GPRMC['raw']['knots'],
|
1695 |
+
$GPS_this_GPRMC['raw']['angle'],
|
1696 |
+
$GPS_this_GPRMC['raw']['datestamp'],
|
1697 |
+
$GPS_this_GPRMC['raw']['variation'],
|
1698 |
+
$GPS_this_GPRMC['raw']['variation_direction'],
|
1699 |
+
$dummy,
|
1700 |
+
$GPS_this_GPRMC['raw']['checksum'],
|
1701 |
+
) = $matches;
|
1702 |
+
|
1703 |
+
$hour = substr($GPS_this_GPRMC['raw']['timestamp'], 0, 2);
|
1704 |
+
$minute = substr($GPS_this_GPRMC['raw']['timestamp'], 2, 2);
|
1705 |
+
$second = substr($GPS_this_GPRMC['raw']['timestamp'], 4, 2);
|
1706 |
+
$ms = substr($GPS_this_GPRMC['raw']['timestamp'], 6); // may contain decimal seconds
|
1707 |
+
$day = substr($GPS_this_GPRMC['raw']['datestamp'], 0, 2);
|
1708 |
+
$month = substr($GPS_this_GPRMC['raw']['datestamp'], 2, 2);
|
1709 |
+
$year = substr($GPS_this_GPRMC['raw']['datestamp'], 4, 2);
|
1710 |
+
$year += (($year > 90) ? 1900 : 2000); // complete lack of foresight: datestamps are stored with 2-digit years, take best guess
|
1711 |
+
$GPS_this_GPRMC['timestamp'] = $year.'-'.$month.'-'.$day.' '.$hour.':'.$minute.':'.$second.$ms;
|
1712 |
+
|
1713 |
+
$GPS_this_GPRMC['active'] = ($GPS_this_GPRMC['raw']['status'] == 'A'); // A=Active,V=Void
|
1714 |
+
|
1715 |
+
foreach (array('latitude','longitude') as $latlon) {
|
1716 |
+
preg_match('#^([0-9]{1,3})([0-9]{2}\\.[0-9]+)$#', $GPS_this_GPRMC['raw'][$latlon], $matches);
|
1717 |
+
list($dummy, $deg, $min) = $matches;
|
1718 |
+
$GPS_this_GPRMC[$latlon] = $deg + ($min / 60);
|
1719 |
+
}
|
1720 |
+
$GPS_this_GPRMC['latitude'] *= (($GPS_this_GPRMC['raw']['latitude_direction'] == 'S') ? -1 : 1);
|
1721 |
+
$GPS_this_GPRMC['longitude'] *= (($GPS_this_GPRMC['raw']['longitude_direction'] == 'W') ? -1 : 1);
|
1722 |
+
|
1723 |
+
$GPS_this_GPRMC['heading'] = $GPS_this_GPRMC['raw']['angle'];
|
1724 |
+
$GPS_this_GPRMC['speed_knot'] = $GPS_this_GPRMC['raw']['knots'];
|
1725 |
+
$GPS_this_GPRMC['speed_kmh'] = $GPS_this_GPRMC['raw']['knots'] * 1.852;
|
1726 |
+
if ($GPS_this_GPRMC['raw']['variation']) {
|
1727 |
+
$GPS_this_GPRMC['variation'] = $GPS_this_GPRMC['raw']['variation'];
|
1728 |
+
$GPS_this_GPRMC['variation'] *= (($GPS_this_GPRMC['raw']['variation_direction'] == 'W') ? -1 : 1);
|
1729 |
+
}
|
1730 |
|
1731 |
+
$atom_structure['gps_entries'][$key] = $GPS_this_GPRMC;
|
1732 |
+
|
1733 |
+
@$info['quicktime']['gps_track'][$GPS_this_GPRMC['timestamp']] = array(
|
1734 |
+
'latitude' => (float) $GPS_this_GPRMC['latitude'],
|
1735 |
+
'longitude' => (float) $GPS_this_GPRMC['longitude'],
|
1736 |
+
'speed_kmh' => (float) $GPS_this_GPRMC['speed_kmh'],
|
1737 |
+
'heading' => (float) $GPS_this_GPRMC['heading'],
|
1738 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1739 |
|
1740 |
+
} else {
|
1741 |
+
$this->warning('Unhandled GPS format in "free" atom at offset '.$gps_pointer['offset']);
|
1742 |
+
}
|
1743 |
+
}
|
1744 |
+
$this->fseek($previous_offset);
|
1745 |
+
|
1746 |
+
} else {
|
1747 |
+
$this->warning('QuickTime atom "'.$atomname.'" is not mod-8 bytes long ('.$atomsize.' bytes) at offset '.$baseoffset);
|
1748 |
+
}
|
1749 |
+
} else {
|
1750 |
+
$this->warning('QuickTime atom "'.$atomname.'" is zero bytes long at offset '.$baseoffset);
|
1751 |
}
|
1752 |
+
break;
|
|
|
|
|
|
|
1753 |
|
1754 |
+
case 'loci':// 3GP location (El Loco)
|
1755 |
+
$loffset = 0;
|
1756 |
+
$info['quicktime']['comments']['gps_flags'] = array( getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)));
|
1757 |
+
$info['quicktime']['comments']['gps_lang'] = array( getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)));
|
1758 |
+
$info['quicktime']['comments']['gps_location'] = array( $this->LociString(substr($atom_data, 6), $loffset));
|
1759 |
+
$loci_data = substr($atom_data, 6 + $loffset);
|
1760 |
+
$info['quicktime']['comments']['gps_role'] = array( getid3_lib::BigEndian2Int(substr($loci_data, 0, 1)));
|
1761 |
+
$info['quicktime']['comments']['gps_longitude'] = array(getid3_lib::FixedPoint16_16(substr($loci_data, 1, 4)));
|
1762 |
+
$info['quicktime']['comments']['gps_latitude'] = array(getid3_lib::FixedPoint16_16(substr($loci_data, 5, 4)));
|
1763 |
+
$info['quicktime']['comments']['gps_altitude'] = array(getid3_lib::FixedPoint16_16(substr($loci_data, 9, 4)));
|
1764 |
+
$info['quicktime']['comments']['gps_body'] = array( $this->LociString(substr($loci_data, 13 ), $loffset));
|
1765 |
+
$info['quicktime']['comments']['gps_notes'] = array( $this->LociString(substr($loci_data, 13 + $loffset), $loffset));
|
1766 |
+
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1767 |
|
1768 |
+
case 'chpl': // CHaPter List
|
1769 |
+
// https://www.adobe.com/content/dam/Adobe/en/devnet/flv/pdfs/video_file_format_spec_v10.pdf
|
1770 |
+
$chpl_version = getid3_lib::BigEndian2Int(substr($atom_data, 4, 1)); // Expected to be 0
|
1771 |
+
$chpl_flags = getid3_lib::BigEndian2Int(substr($atom_data, 5, 3)); // Reserved, set to 0
|
1772 |
+
$chpl_count = getid3_lib::BigEndian2Int(substr($atom_data, 8, 1));
|
1773 |
+
$chpl_offset = 9;
|
1774 |
+
for ($i = 0; $i < $chpl_count; $i++) {
|
1775 |
+
if (($chpl_offset + 9) >= strlen($atom_data)) {
|
1776 |
+
$this->warning('QuickTime chapter '.$i.' extends beyond end of "chpl" atom');
|
1777 |
+
break;
|
1778 |
+
}
|
1779 |
+
$info['quicktime']['chapters'][$i]['timestamp'] = getid3_lib::BigEndian2Int(substr($atom_data, $chpl_offset, 8)) / 10000000; // timestamps are stored as 100-nanosecond units
|
1780 |
+
$chpl_offset += 8;
|
1781 |
+
$chpl_title_size = getid3_lib::BigEndian2Int(substr($atom_data, $chpl_offset, 1));
|
1782 |
+
$chpl_offset += 1;
|
1783 |
+
$info['quicktime']['chapters'][$i]['title'] = substr($atom_data, $chpl_offset, $chpl_title_size);
|
1784 |
+
$chpl_offset += $chpl_title_size;
|
1785 |
+
}
|
1786 |
+
break;
|
1787 |
|
1788 |
+
case 'FIRM': // FIRMware version(?), seen on GoPro Hero4
|
1789 |
+
$info['quicktime']['camera']['firmware'] = $atom_data;
|
1790 |
+
break;
|
|
|
|
|
1791 |
|
1792 |
+
case 'CAME': // FIRMware version(?), seen on GoPro Hero4
|
1793 |
+
$info['quicktime']['camera']['serial_hash'] = unpack('H*', $atom_data);
|
1794 |
+
break;
|
|
|
|
|
|
|
1795 |
|
1796 |
+
case 'dscp':
|
1797 |
+
case 'rcif':
|
1798 |
+
// https://www.getid3.org/phpBB3/viewtopic.php?t=1908
|
1799 |
+
if (substr($atom_data, 0, 7) == "\x00\x00\x00\x00\x55\xC4".'{') {
|
1800 |
+
if ($json_decoded = @json_decode(rtrim(substr($atom_data, 6), "\x00"), true)) {
|
1801 |
+
$info['quicktime']['camera'][$atomname] = $json_decoded;
|
1802 |
+
if (($atomname == 'rcif') && isset($info['quicktime']['camera']['rcif']['wxcamera']['rotate'])) {
|
1803 |
+
$info['video']['rotate'] = $info['quicktime']['video']['rotate'] = $info['quicktime']['camera']['rcif']['wxcamera']['rotate'];
|
1804 |
+
}
|
1805 |
+
} else {
|
1806 |
+
$this->warning('Failed to JSON decode atom "'.$atomname.'"');
|
1807 |
+
$atom_structure['data'] = $atom_data;
|
1808 |
+
}
|
1809 |
+
unset($json_decoded);
|
1810 |
+
} else {
|
1811 |
+
$this->warning('Expecting 55 C4 7B at start of atom "'.$atomname.'", found '.getid3_lib::PrintHexBytes(substr($atom_data, 4, 3)).' instead');
|
1812 |
+
$atom_structure['data'] = $atom_data;
|
1813 |
+
}
|
1814 |
+
break;
|
1815 |
+
|
1816 |
+
case 'frea':
|
1817 |
+
// https://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Kodak.html#frea
|
1818 |
+
// may contain "scra" (PreviewImage) and/or "thma" (ThumbnailImage)
|
1819 |
+
$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 4, $atomHierarchy, $ParseAllPossibleAtoms);
|
1820 |
+
break;
|
1821 |
+
case 'tima': // subatom to "frea"
|
1822 |
+
// no idea what this does, the one sample file I've seen has a value of 0x00000027
|
1823 |
+
$atom_structure['data'] = $atom_data;
|
1824 |
+
break;
|
1825 |
+
case 'ver ': // subatom to "frea"
|
1826 |
+
// some kind of version number, the one sample file I've seen has a value of "3.00.073"
|
1827 |
+
$atom_structure['data'] = $atom_data;
|
1828 |
+
break;
|
1829 |
+
case 'thma': // subatom to "frea" -- "ThumbnailImage"
|
1830 |
+
// https://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Kodak.html#frea
|
1831 |
+
if (strlen($atom_data) > 0) {
|
1832 |
+
$info['quicktime']['comments']['picture'][] = array('data'=>$atom_data, 'image_mime'=>'image/jpeg');
|
1833 |
+
}
|
1834 |
+
break;
|
1835 |
+
case 'scra': // subatom to "frea" -- "PreviewImage"
|
1836 |
+
// https://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Kodak.html#frea
|
1837 |
+
// but the only sample file I've seen has no useful data here
|
1838 |
+
if (strlen($atom_data) > 0) {
|
1839 |
+
$info['quicktime']['comments']['picture'][] = array('data'=>$atom_data, 'image_mime'=>'image/jpeg');
|
1840 |
+
}
|
1841 |
+
break;
|
1842 |
+
|
1843 |
+
|
1844 |
+
default:
|
1845 |
+
$this->warning('Unknown QuickTime atom type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" ('.trim(getid3_lib::PrintHexBytes($atomname)).'), '.$atomsize.' bytes at offset '.$baseoffset);
|
1846 |
+
$atom_structure['data'] = $atom_data;
|
1847 |
+
break;
|
1848 |
+
}
|
1849 |
}
|
1850 |
array_pop($atomHierarchy);
|
1851 |
return $atom_structure;
|
1852 |
}
|
1853 |
|
1854 |
+
/**
|
1855 |
+
* @param string $atom_data
|
1856 |
+
* @param int $baseoffset
|
1857 |
+
* @param array $atomHierarchy
|
1858 |
+
* @param bool $ParseAllPossibleAtoms
|
1859 |
+
*
|
1860 |
+
* @return array|false
|
1861 |
+
*/
|
1862 |
public function QuicktimeParseContainerAtom($atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) {
|
|
|
1863 |
$atom_structure = false;
|
1864 |
$subatomoffset = 0;
|
1865 |
$subatomcounter = 0;
|
1874 |
// Furthermore, for historical reasons the list of atoms is optionally
|
1875 |
// terminated by a 32-bit integer set to 0. If you are writing a program
|
1876 |
// to read user data atoms, you should allow for the terminating 0.
|
1877 |
+
if (strlen($atom_data) > 12) {
|
1878 |
+
$subatomoffset += 4;
|
1879 |
+
continue;
|
1880 |
+
}
|
1881 |
return $atom_structure;
|
1882 |
}
|
1883 |
+
$atom_structure[$subatomcounter++] = $this->QuicktimeParseAtom($subatomname, $subatomsize, $subatomdata, $baseoffset + $subatomoffset, $atomHierarchy, $ParseAllPossibleAtoms);
|
|
|
|
|
1884 |
$subatomoffset += $subatomsize;
|
|
|
1885 |
}
|
1886 |
return $atom_structure;
|
1887 |
}
|
1888 |
|
1889 |
+
/**
|
1890 |
+
* @param string $data
|
1891 |
+
* @param int $offset
|
1892 |
+
*
|
1893 |
+
* @return int
|
1894 |
+
*/
|
1895 |
public function quicktime_read_mp4_descr_length($data, &$offset) {
|
1896 |
// http://libquicktime.sourcearchive.com/documentation/2:1.0.2plus-pdebian-2build1/esds_8c-source.html
|
1897 |
$num_bytes = 0;
|
1903 |
return $length;
|
1904 |
}
|
1905 |
|
1906 |
+
/**
|
1907 |
+
* @param int $languageid
|
1908 |
+
*
|
1909 |
+
* @return string
|
1910 |
+
*/
|
1911 |
public function QuicktimeLanguageLookup($languageid) {
|
1912 |
// http://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap4/qtff4.html#//apple_ref/doc/uid/TP40000939-CH206-34353
|
1913 |
static $QuicktimeLanguageLookup = array();
|
2045 |
return (isset($QuicktimeLanguageLookup[$languageid]) ? $QuicktimeLanguageLookup[$languageid] : 'invalid');
|
2046 |
}
|
2047 |
|
2048 |
+
/**
|
2049 |
+
* @param string $codecid
|
2050 |
+
*
|
2051 |
+
* @return string
|
2052 |
+
*/
|
2053 |
public function QuicktimeVideoCodecLookup($codecid) {
|
2054 |
static $QuicktimeVideoCodecLookup = array();
|
2055 |
if (empty($QuicktimeVideoCodecLookup)) {
|
2109 |
return (isset($QuicktimeVideoCodecLookup[$codecid]) ? $QuicktimeVideoCodecLookup[$codecid] : '');
|
2110 |
}
|
2111 |
|
2112 |
+
/**
|
2113 |
+
* @param string $codecid
|
2114 |
+
*
|
2115 |
+
* @return mixed|string
|
2116 |
+
*/
|
2117 |
public function QuicktimeAudioCodecLookup($codecid) {
|
2118 |
static $QuicktimeAudioCodecLookup = array();
|
2119 |
if (empty($QuicktimeAudioCodecLookup)) {
|
2159 |
return (isset($QuicktimeAudioCodecLookup[$codecid]) ? $QuicktimeAudioCodecLookup[$codecid] : '');
|
2160 |
}
|
2161 |
|
2162 |
+
/**
|
2163 |
+
* @param string $compressionid
|
2164 |
+
*
|
2165 |
+
* @return string
|
2166 |
+
*/
|
2167 |
public function QuicktimeDCOMLookup($compressionid) {
|
2168 |
static $QuicktimeDCOMLookup = array();
|
2169 |
if (empty($QuicktimeDCOMLookup)) {
|
2173 |
return (isset($QuicktimeDCOMLookup[$compressionid]) ? $QuicktimeDCOMLookup[$compressionid] : '');
|
2174 |
}
|
2175 |
|
2176 |
+
/**
|
2177 |
+
* @param int $colordepthid
|
2178 |
+
*
|
2179 |
+
* @return string
|
2180 |
+
*/
|
2181 |
public function QuicktimeColorNameLookup($colordepthid) {
|
2182 |
static $QuicktimeColorNameLookup = array();
|
2183 |
if (empty($QuicktimeColorNameLookup)) {
|
2196 |
return (isset($QuicktimeColorNameLookup[$colordepthid]) ? $QuicktimeColorNameLookup[$colordepthid] : 'invalid');
|
2197 |
}
|
2198 |
|
2199 |
+
/**
|
2200 |
+
* @param int $stik
|
2201 |
+
*
|
2202 |
+
* @return string
|
2203 |
+
*/
|
2204 |
public function QuicktimeSTIKLookup($stik) {
|
2205 |
static $QuicktimeSTIKLookup = array();
|
2206 |
if (empty($QuicktimeSTIKLookup)) {
|
2218 |
return (isset($QuicktimeSTIKLookup[$stik]) ? $QuicktimeSTIKLookup[$stik] : 'invalid');
|
2219 |
}
|
2220 |
|
2221 |
+
/**
|
2222 |
+
* @param int $audio_profile_id
|
2223 |
+
*
|
2224 |
+
* @return string
|
2225 |
+
*/
|
2226 |
public function QuicktimeIODSaudioProfileName($audio_profile_id) {
|
2227 |
static $QuicktimeIODSaudioProfileNameLookup = array();
|
2228 |
if (empty($QuicktimeIODSaudioProfileNameLookup)) {
|
2229 |
$QuicktimeIODSaudioProfileNameLookup = array(
|
2230 |
+
0x00 => 'ISO Reserved (0x00)',
|
2231 |
+
0x01 => 'Main Audio Profile @ Level 1',
|
2232 |
+
0x02 => 'Main Audio Profile @ Level 2',
|
2233 |
+
0x03 => 'Main Audio Profile @ Level 3',
|
2234 |
+
0x04 => 'Main Audio Profile @ Level 4',
|
2235 |
+
0x05 => 'Scalable Audio Profile @ Level 1',
|
2236 |
+
0x06 => 'Scalable Audio Profile @ Level 2',
|
2237 |
+
0x07 => 'Scalable Audio Profile @ Level 3',
|
2238 |
+
0x08 => 'Scalable Audio Profile @ Level 4',
|
2239 |
+
0x09 => 'Speech Audio Profile @ Level 1',
|
2240 |
+
0x0A => 'Speech Audio Profile @ Level 2',
|
2241 |
+
0x0B => 'Synthetic Audio Profile @ Level 1',
|
2242 |
+
0x0C => 'Synthetic Audio Profile @ Level 2',
|
2243 |
+
0x0D => 'Synthetic Audio Profile @ Level 3',
|
2244 |
+
0x0E => 'High Quality Audio Profile @ Level 1',
|
2245 |
+
0x0F => 'High Quality Audio Profile @ Level 2',
|
2246 |
+
0x10 => 'High Quality Audio Profile @ Level 3',
|
2247 |
+
0x11 => 'High Quality Audio Profile @ Level 4',
|
2248 |
+
0x12 => 'High Quality Audio Profile @ Level 5',
|
2249 |
+
0x13 => 'High Quality Audio Profile @ Level 6',
|
2250 |
+
0x14 => 'High Quality Audio Profile @ Level 7',
|
2251 |
+
0x15 => 'High Quality Audio Profile @ Level 8',
|
2252 |
+
0x16 => 'Low Delay Audio Profile @ Level 1',
|
2253 |
+
0x17 => 'Low Delay Audio Profile @ Level 2',
|
2254 |
+
0x18 => 'Low Delay Audio Profile @ Level 3',
|
2255 |
+
0x19 => 'Low Delay Audio Profile @ Level 4',
|
2256 |
+
0x1A => 'Low Delay Audio Profile @ Level 5',
|
2257 |
+
0x1B => 'Low Delay Audio Profile @ Level 6',
|
2258 |
+
0x1C => 'Low Delay Audio Profile @ Level 7',
|
2259 |
+
0x1D => 'Low Delay Audio Profile @ Level 8',
|
2260 |
+
0x1E => 'Natural Audio Profile @ Level 1',
|
2261 |
+
0x1F => 'Natural Audio Profile @ Level 2',
|
2262 |
+
0x20 => 'Natural Audio Profile @ Level 3',
|
2263 |
+
0x21 => 'Natural Audio Profile @ Level 4',
|
2264 |
+
0x22 => 'Mobile Audio Internetworking Profile @ Level 1',
|
2265 |
+
0x23 => 'Mobile Audio Internetworking Profile @ Level 2',
|
2266 |
+
0x24 => 'Mobile Audio Internetworking Profile @ Level 3',
|
2267 |
+
0x25 => 'Mobile Audio Internetworking Profile @ Level 4',
|
2268 |
+
0x26 => 'Mobile Audio Internetworking Profile @ Level 5',
|
2269 |
+
0x27 => 'Mobile Audio Internetworking Profile @ Level 6',
|
2270 |
+
0x28 => 'AAC Profile @ Level 1',
|
2271 |
+
0x29 => 'AAC Profile @ Level 2',
|
2272 |
+
0x2A => 'AAC Profile @ Level 4',
|
2273 |
+
0x2B => 'AAC Profile @ Level 5',
|
2274 |
+
0x2C => 'High Efficiency AAC Profile @ Level 2',
|
2275 |
+
0x2D => 'High Efficiency AAC Profile @ Level 3',
|
2276 |
+
0x2E => 'High Efficiency AAC Profile @ Level 4',
|
2277 |
+
0x2F => 'High Efficiency AAC Profile @ Level 5',
|
2278 |
+
0xFE => 'Not part of MPEG-4 audio profiles',
|
2279 |
+
0xFF => 'No audio capability required',
|
2280 |
);
|
2281 |
}
|
2282 |
return (isset($QuicktimeIODSaudioProfileNameLookup[$audio_profile_id]) ? $QuicktimeIODSaudioProfileNameLookup[$audio_profile_id] : 'ISO Reserved / User Private');
|
2283 |
}
|
2284 |
|
2285 |
+
/**
|
2286 |
+
* @param int $video_profile_id
|
2287 |
+
*
|
2288 |
+
* @return string
|
2289 |
+
*/
|
2290 |
public function QuicktimeIODSvideoProfileName($video_profile_id) {
|
2291 |
static $QuicktimeIODSvideoProfileNameLookup = array();
|
2292 |
if (empty($QuicktimeIODSvideoProfileNameLookup)) {
|
2358 |
return (isset($QuicktimeIODSvideoProfileNameLookup[$video_profile_id]) ? $QuicktimeIODSvideoProfileNameLookup[$video_profile_id] : 'ISO Reserved Profile');
|
2359 |
}
|
2360 |
|
2361 |
+
/**
|
2362 |
+
* @param int $rtng
|
2363 |
+
*
|
2364 |
+
* @return string
|
2365 |
+
*/
|
2366 |
public function QuicktimeContentRatingLookup($rtng) {
|
2367 |
static $QuicktimeContentRatingLookup = array();
|
2368 |
if (empty($QuicktimeContentRatingLookup)) {
|
2373 |
return (isset($QuicktimeContentRatingLookup[$rtng]) ? $QuicktimeContentRatingLookup[$rtng] : 'invalid');
|
2374 |
}
|
2375 |
|
2376 |
+
/**
|
2377 |
+
* @param int $akid
|
2378 |
+
*
|
2379 |
+
* @return string
|
2380 |
+
*/
|
2381 |
public function QuicktimeStoreAccountTypeLookup($akid) {
|
2382 |
static $QuicktimeStoreAccountTypeLookup = array();
|
2383 |
if (empty($QuicktimeStoreAccountTypeLookup)) {
|
2387 |
return (isset($QuicktimeStoreAccountTypeLookup[$akid]) ? $QuicktimeStoreAccountTypeLookup[$akid] : 'invalid');
|
2388 |
}
|
2389 |
|
2390 |
+
/**
|
2391 |
+
* @param int $sfid
|
2392 |
+
*
|
2393 |
+
* @return string
|
2394 |
+
*/
|
2395 |
public function QuicktimeStoreFrontCodeLookup($sfid) {
|
2396 |
static $QuicktimeStoreFrontCodeLookup = array();
|
2397 |
if (empty($QuicktimeStoreFrontCodeLookup)) {
|
2421 |
return (isset($QuicktimeStoreFrontCodeLookup[$sfid]) ? $QuicktimeStoreFrontCodeLookup[$sfid] : 'invalid');
|
2422 |
}
|
2423 |
|
2424 |
+
/**
|
2425 |
+
* @param string $atom_data
|
2426 |
+
*
|
2427 |
+
* @return array
|
2428 |
+
*/
|
2429 |
public function QuicktimeParseNikonNCTG($atom_data) {
|
2430 |
// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG
|
2431 |
// Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from some Nikon cameras such as the Coolpix S8000 and D5100
|
2468 |
);
|
2469 |
|
2470 |
$offset = 0;
|
2471 |
+
$data = null;
|
2472 |
$datalength = strlen($atom_data);
|
2473 |
$parsed = array();
|
2474 |
while ($offset < $datalength) {
|
|
|
2475 |
$record_type = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 4)); $offset += 4;
|
2476 |
$data_size_type = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2)); $offset += 2;
|
2477 |
$data_size = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2)); $offset += 2;
|
2526 |
$offset += ($data_size * 2);
|
2527 |
break;
|
2528 |
default:
|
2529 |
+
echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br>';
|
2530 |
break 2;
|
2531 |
}
|
2532 |
|
2604 |
return $parsed;
|
2605 |
}
|
2606 |
|
2607 |
+
/**
|
2608 |
+
* @param string $keyname
|
2609 |
+
* @param string|array $data
|
2610 |
+
* @param string $boxname
|
2611 |
+
*
|
2612 |
+
* @return bool
|
2613 |
+
*/
|
2614 |
public function CopyToAppropriateCommentsSection($keyname, $data, $boxname='') {
|
2615 |
static $handyatomtranslatorarray = array();
|
2616 |
if (empty($handyatomtranslatorarray)) {
|
2707 |
$handyatomtranslatorarray['MusicBrainz Disc Id'] = 'MusicBrainz Disc Id';
|
2708 |
|
2709 |
// http://age.hobba.nl/audio/tag_frame_reference.html
|
2710 |
+
$handyatomtranslatorarray['PLAY_COUNTER'] = 'play_counter'; // Foobar2000 - https://www.getid3.org/phpBB3/viewtopic.php?t=1355
|
2711 |
+
$handyatomtranslatorarray['MEDIATYPE'] = 'mediatype'; // Foobar2000 - https://www.getid3.org/phpBB3/viewtopic.php?t=1355
|
2712 |
*/
|
2713 |
}
|
2714 |
$info = &$this->getid3->info;
|
2734 |
$data = array('data'=>$data, 'image_mime'=>$image_mime);
|
2735 |
}
|
2736 |
}
|
2737 |
+
$gooddata = array($data);
|
2738 |
+
if ($comment_key == 'genre') {
|
2739 |
+
// some other taggers separate multiple genres with semicolon, e.g. "Heavy Metal;Thrash Metal;Metal"
|
2740 |
+
$gooddata = explode(';', $data);
|
2741 |
+
}
|
2742 |
+
foreach ($gooddata as $data) {
|
2743 |
+
$info['quicktime']['comments'][$comment_key][] = $data;
|
2744 |
+
}
|
2745 |
}
|
2746 |
return true;
|
2747 |
}
|
2748 |
|
2749 |
+
/**
|
2750 |
+
* @param string $lstring
|
2751 |
+
* @param int $count
|
2752 |
+
*
|
2753 |
+
* @return string
|
2754 |
+
*/
|
2755 |
+
public function LociString($lstring, &$count) {
|
2756 |
+
// Loci strings are UTF-8 or UTF-16 and null (x00/x0000) terminated. UTF-16 has a BOM
|
2757 |
+
// Also need to return the number of bytes the string occupied so additional fields can be extracted
|
2758 |
+
$len = strlen($lstring);
|
2759 |
+
if ($len == 0) {
|
2760 |
+
$count = 0;
|
2761 |
+
return '';
|
2762 |
+
}
|
2763 |
+
if ($lstring[0] == "\x00") {
|
2764 |
+
$count = 1;
|
2765 |
+
return '';
|
2766 |
+
}
|
2767 |
+
// check for BOM
|
2768 |
+
if (($len > 2) && ((($lstring[0] == "\xFE") && ($lstring[1] == "\xFF")) || (($lstring[0] == "\xFF") && ($lstring[1] == "\xFE")))) {
|
2769 |
+
// UTF-16
|
2770 |
+
if (preg_match('/(.*)\x00/', $lstring, $lmatches)) {
|
2771 |
+
$count = strlen($lmatches[1]) * 2 + 2; //account for 2 byte characters and trailing \x0000
|
2772 |
+
return getid3_lib::iconv_fallback_utf16_utf8($lmatches[1]);
|
2773 |
+
} else {
|
2774 |
+
return '';
|
2775 |
+
}
|
2776 |
+
}
|
2777 |
+
// UTF-8
|
2778 |
+
if (preg_match('/(.*)\x00/', $lstring, $lmatches)) {
|
2779 |
+
$count = strlen($lmatches[1]) + 1; //account for trailing \x00
|
2780 |
+
return $lmatches[1];
|
2781 |
+
}
|
2782 |
+
return '';
|
2783 |
+
}
|
2784 |
+
|
2785 |
+
/**
|
2786 |
+
* @param string $nullterminatedstring
|
2787 |
+
*
|
2788 |
+
* @return string
|
2789 |
+
*/
|
2790 |
public function NoNullString($nullterminatedstring) {
|
2791 |
// remove the single null terminator on null terminated strings
|
2792 |
if (substr($nullterminatedstring, strlen($nullterminatedstring) - 1, 1) === "\x00") {
|
2795 |
return $nullterminatedstring;
|
2796 |
}
|
2797 |
|
2798 |
+
/**
|
2799 |
+
* @param string $pascalstring
|
2800 |
+
*
|
2801 |
+
* @return string
|
2802 |
+
*/
|
2803 |
public function Pascal2String($pascalstring) {
|
2804 |
// Pascal strings have 1 unsigned byte at the beginning saying how many chars (1-255) are in the string
|
2805 |
return substr($pascalstring, 1);
|
2806 |
}
|
2807 |
|
2808 |
+
|
2809 |
+
/**
|
2810 |
+
* Helper functions for m4b audiobook chapters
|
2811 |
+
* code by Steffen Hartmann 2015-Nov-08.
|
2812 |
+
*
|
2813 |
+
* @param array $info
|
2814 |
+
* @param string $tag
|
2815 |
+
* @param string $history
|
2816 |
+
* @param array $result
|
2817 |
+
*/
|
2818 |
+
public function search_tag_by_key($info, $tag, $history, &$result) {
|
2819 |
+
foreach ($info as $key => $value) {
|
2820 |
+
$key_history = $history.'/'.$key;
|
2821 |
+
if ($key === $tag) {
|
2822 |
+
$result[] = array($key_history, $info);
|
2823 |
+
} else {
|
2824 |
+
if (is_array($value)) {
|
2825 |
+
$this->search_tag_by_key($value, $tag, $key_history, $result);
|
2826 |
+
}
|
2827 |
+
}
|
2828 |
+
}
|
2829 |
+
}
|
2830 |
+
|
2831 |
+
/**
|
2832 |
+
* @param array $info
|
2833 |
+
* @param string $k
|
2834 |
+
* @param string $v
|
2835 |
+
* @param string $history
|
2836 |
+
* @param array $result
|
2837 |
+
*/
|
2838 |
+
public function search_tag_by_pair($info, $k, $v, $history, &$result) {
|
2839 |
+
foreach ($info as $key => $value) {
|
2840 |
+
$key_history = $history.'/'.$key;
|
2841 |
+
if (($key === $k) && ($value === $v)) {
|
2842 |
+
$result[] = array($key_history, $info);
|
2843 |
+
} else {
|
2844 |
+
if (is_array($value)) {
|
2845 |
+
$this->search_tag_by_pair($value, $k, $v, $key_history, $result);
|
2846 |
+
}
|
2847 |
+
}
|
2848 |
+
}
|
2849 |
+
}
|
2850 |
+
|
2851 |
+
/**
|
2852 |
+
* @param array $info
|
2853 |
+
*
|
2854 |
+
* @return array
|
2855 |
+
*/
|
2856 |
+
public function quicktime_time_to_sample_table($info) {
|
2857 |
+
$res = array();
|
2858 |
+
$this->search_tag_by_pair($info['quicktime']['moov'], 'name', 'stbl', 'quicktime/moov', $res);
|
2859 |
+
foreach ($res as $value) {
|
2860 |
+
$stbl_res = array();
|
2861 |
+
$this->search_tag_by_pair($value[1], 'data_format', 'text', $value[0], $stbl_res);
|
2862 |
+
if (count($stbl_res) > 0) {
|
2863 |
+
$stts_res = array();
|
2864 |
+
$this->search_tag_by_key($value[1], 'time_to_sample_table', $value[0], $stts_res);
|
2865 |
+
if (count($stts_res) > 0) {
|
2866 |
+
return $stts_res[0][1]['time_to_sample_table'];
|
2867 |
+
}
|
2868 |
+
}
|
2869 |
+
}
|
2870 |
+
return array();
|
2871 |
+
}
|
2872 |
+
|
2873 |
+
/**
|
2874 |
+
* @param array $info
|
2875 |
+
*
|
2876 |
+
* @return int
|
2877 |
+
*/
|
2878 |
+
public function quicktime_bookmark_time_scale($info) {
|
2879 |
+
$time_scale = '';
|
2880 |
+
$ts_prefix_len = 0;
|
2881 |
+
$res = array();
|
2882 |
+
$this->search_tag_by_pair($info['quicktime']['moov'], 'name', 'stbl', 'quicktime/moov', $res);
|
2883 |
+
foreach ($res as $value) {
|
2884 |
+
$stbl_res = array();
|
2885 |
+
$this->search_tag_by_pair($value[1], 'data_format', 'text', $value[0], $stbl_res);
|
2886 |
+
if (count($stbl_res) > 0) {
|
2887 |
+
$ts_res = array();
|
2888 |
+
$this->search_tag_by_key($info['quicktime']['moov'], 'time_scale', 'quicktime/moov', $ts_res);
|
2889 |
+
foreach ($ts_res as $sub_value) {
|
2890 |
+
$prefix = substr($sub_value[0], 0, -12);
|
2891 |
+
if ((substr($stbl_res[0][0], 0, strlen($prefix)) === $prefix) && ($ts_prefix_len < strlen($prefix))) {
|
2892 |
+
$time_scale = $sub_value[1]['time_scale'];
|
2893 |
+
$ts_prefix_len = strlen($prefix);
|
2894 |
+
}
|
2895 |
+
}
|
2896 |
+
}
|
2897 |
+
}
|
2898 |
+
return $time_scale;
|
2899 |
+
}
|
2900 |
+
/*
|
2901 |
+
// END helper functions for m4b audiobook chapters
|
2902 |
+
*/
|
2903 |
+
|
2904 |
+
|
2905 |
}
|
lib/getid3/module.audio-video.real.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio-video.real.php //
|
@@ -18,7 +18,9 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php',
|
|
18 |
|
19 |
class getid3_real extends getid3_handler
|
20 |
{
|
21 |
-
|
|
|
|
|
22 |
public function Analyze() {
|
23 |
$info = &$this->getid3->info;
|
24 |
|
@@ -53,7 +55,7 @@ class getid3_real extends getid3_handler
|
|
53 |
}
|
54 |
return true;
|
55 |
}
|
56 |
-
$
|
57 |
unset($info['bitrate']);
|
58 |
unset($info['playtime_seconds']);
|
59 |
return false;
|
@@ -67,7 +69,7 @@ class getid3_real extends getid3_handler
|
|
67 |
$thisfile_real_chunks_currentchunk['offset'] = $this->ftell() - 8;
|
68 |
$thisfile_real_chunks_currentchunk['length'] = $ChunkSize;
|
69 |
if (($thisfile_real_chunks_currentchunk['offset'] + $thisfile_real_chunks_currentchunk['length']) > $info['avdataend']) {
|
70 |
-
$
|
71 |
return false;
|
72 |
}
|
73 |
|
@@ -98,7 +100,7 @@ class getid3_real extends getid3_handler
|
|
98 |
break;
|
99 |
|
100 |
default:
|
101 |
-
//$
|
102 |
break;
|
103 |
|
104 |
}
|
@@ -354,7 +356,7 @@ class getid3_real extends getid3_handler
|
|
354 |
break;
|
355 |
|
356 |
default:
|
357 |
-
$
|
358 |
break;
|
359 |
}
|
360 |
$ChunkCounter++;
|
@@ -370,7 +372,12 @@ class getid3_real extends getid3_handler
|
|
370 |
return true;
|
371 |
}
|
372 |
|
373 |
-
|
|
|
|
|
|
|
|
|
|
|
374 |
public function ParseOldRAheader($OldRAheaderData, &$ParsedArray) {
|
375 |
// http://www.freelists.org/archives/matroska-devel/07-2003/msg00010.html
|
376 |
|
@@ -485,6 +492,12 @@ class getid3_real extends getid3_handler
|
|
485 |
return true;
|
486 |
}
|
487 |
|
|
|
|
|
|
|
|
|
|
|
|
|
488 |
public function RealAudioCodecFourCClookup($fourcc, $bitrate) {
|
489 |
static $RealAudioCodecFourCClookup = array();
|
490 |
if (empty($RealAudioCodecFourCClookup)) {
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio-video.real.php //
|
18 |
|
19 |
class getid3_real extends getid3_handler
|
20 |
{
|
21 |
+
/**
|
22 |
+
* @return bool
|
23 |
+
*/
|
24 |
public function Analyze() {
|
25 |
$info = &$this->getid3->info;
|
26 |
|
55 |
}
|
56 |
return true;
|
57 |
}
|
58 |
+
$this->error('There was a problem parsing this RealAudio file. Please submit it for analysis to info@getid3.org');
|
59 |
unset($info['bitrate']);
|
60 |
unset($info['playtime_seconds']);
|
61 |
return false;
|
69 |
$thisfile_real_chunks_currentchunk['offset'] = $this->ftell() - 8;
|
70 |
$thisfile_real_chunks_currentchunk['length'] = $ChunkSize;
|
71 |
if (($thisfile_real_chunks_currentchunk['offset'] + $thisfile_real_chunks_currentchunk['length']) > $info['avdataend']) {
|
72 |
+
$this->warning('Chunk "'.$thisfile_real_chunks_currentchunk['name'].'" at offset '.$thisfile_real_chunks_currentchunk['offset'].' claims to be '.$thisfile_real_chunks_currentchunk['length'].' bytes long, which is beyond end of file');
|
73 |
return false;
|
74 |
}
|
75 |
|
100 |
break;
|
101 |
|
102 |
default:
|
103 |
+
//$this->warning('Expected .RMF-object_version to be "0", actual value is "'.$thisfile_real_chunks_currentchunk['object_version'].'" (should not be a problem)');
|
104 |
break;
|
105 |
|
106 |
}
|
356 |
break;
|
357 |
|
358 |
default:
|
359 |
+
$this->warning('Unhandled RealMedia chunk "'.$ChunkName.'" at offset '.$thisfile_real_chunks_currentchunk['offset']);
|
360 |
break;
|
361 |
}
|
362 |
$ChunkCounter++;
|
372 |
return true;
|
373 |
}
|
374 |
|
375 |
+
/**
|
376 |
+
* @param string $OldRAheaderData
|
377 |
+
* @param array $ParsedArray
|
378 |
+
*
|
379 |
+
* @return bool
|
380 |
+
*/
|
381 |
public function ParseOldRAheader($OldRAheaderData, &$ParsedArray) {
|
382 |
// http://www.freelists.org/archives/matroska-devel/07-2003/msg00010.html
|
383 |
|
492 |
return true;
|
493 |
}
|
494 |
|
495 |
+
/**
|
496 |
+
* @param string $fourcc
|
497 |
+
* @param int $bitrate
|
498 |
+
*
|
499 |
+
* @return string
|
500 |
+
*/
|
501 |
public function RealAudioCodecFourCClookup($fourcc, $bitrate) {
|
502 |
static $RealAudioCodecFourCClookup = array();
|
503 |
if (empty($RealAudioCodecFourCClookup)) {
|
lib/getid3/module.audio-video.riff.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio-video.riff.php //
|
@@ -27,10 +27,15 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE_
|
|
27 |
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ac3.php', __FILE__, true);
|
28 |
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.dts.php', __FILE__, true);
|
29 |
|
30 |
-
class getid3_riff extends getid3_handler
|
31 |
-
|
32 |
protected $container = 'riff'; // default
|
33 |
|
|
|
|
|
|
|
|
|
|
|
34 |
public function Analyze() {
|
35 |
$info = &$this->getid3->info;
|
36 |
|
@@ -46,6 +51,7 @@ class getid3_riff extends getid3_handler {
|
|
46 |
$thisfile_audio_dataformat = &$thisfile_audio['dataformat'];
|
47 |
$thisfile_riff_audio = &$thisfile_riff['audio'];
|
48 |
$thisfile_riff_video = &$thisfile_riff['video'];
|
|
|
49 |
|
50 |
$Original['avdataoffset'] = $info['avdataoffset'];
|
51 |
$Original['avdataend'] = $info['avdataend'];
|
@@ -190,7 +196,7 @@ class getid3_riff extends getid3_handler {
|
|
190 |
$thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($thisfile_riff_WAVE['fmt '][0]['data']);
|
191 |
$thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
|
192 |
if (!isset($thisfile_riff_audio[$streamindex]['bitrate']) || ($thisfile_riff_audio[$streamindex]['bitrate'] == 0)) {
|
193 |
-
$
|
194 |
return false;
|
195 |
}
|
196 |
$thisfile_riff_raw['fmt '] = $thisfile_riff_audio[$streamindex]['raw'];
|
@@ -199,7 +205,7 @@ class getid3_riff extends getid3_handler {
|
|
199 |
|
200 |
$thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
|
201 |
if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') {
|
202 |
-
$
|
203 |
}
|
204 |
$thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
|
205 |
|
@@ -302,10 +308,10 @@ class getid3_riff extends getid3_handler {
|
|
302 |
list($dummy, $bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second']) = $matches_bext_time;
|
303 |
$thisfile_riff_WAVE_bext_0['origin_date_unix'] = gmmktime($bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second'], $bext_timestamp['month'], $bext_timestamp['day'], $bext_timestamp['year']);
|
304 |
} else {
|
305 |
-
$
|
306 |
}
|
307 |
} else {
|
308 |
-
$
|
309 |
}
|
310 |
$thisfile_riff['comments']['author'][] = $thisfile_riff_WAVE_bext_0['author'];
|
311 |
$thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_bext_0['title'];
|
@@ -357,6 +363,7 @@ class getid3_riff extends getid3_handler {
|
|
357 |
}
|
358 |
$thisfile_riff_WAVE_cart_0['url'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 748, 1024));
|
359 |
$thisfile_riff_WAVE_cart_0['tag_text'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_cart_0['data'], 1772)));
|
|
|
360 |
|
361 |
$thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist'];
|
362 |
$thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_cart_0['title'];
|
@@ -385,10 +392,10 @@ class getid3_riff extends getid3_handler {
|
|
385 |
$SNDM_thisTagOffset += $SNDM_thisTagDataSize;
|
386 |
|
387 |
if ($SNDM_thisTagSize != (4 + 4 + 2 + 2 + $SNDM_thisTagDataSize)) {
|
388 |
-
$
|
389 |
break;
|
390 |
} elseif ($SNDM_thisTagSize <= 0) {
|
391 |
-
$
|
392 |
break;
|
393 |
}
|
394 |
$SNDM_startoffset += $SNDM_thisTagSize;
|
@@ -397,7 +404,7 @@ class getid3_riff extends getid3_handler {
|
|
397 |
if ($parsedkey = self::waveSNDMtagLookup($SNDM_thisTagKey)) {
|
398 |
$thisfile_riff_WAVE_SNDM_0['parsed'][$parsedkey] = $SNDM_thisTagDataText;
|
399 |
} else {
|
400 |
-
$
|
401 |
}
|
402 |
}
|
403 |
|
@@ -405,7 +412,6 @@ class getid3_riff extends getid3_handler {
|
|
405 |
'tracktitle'=>'title',
|
406 |
'category' =>'genre',
|
407 |
'cdtitle' =>'album',
|
408 |
-
'tracktitle'=>'title',
|
409 |
);
|
410 |
foreach ($tagmapping as $fromkey => $tokey) {
|
411 |
if (isset($thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey])) {
|
@@ -428,13 +434,15 @@ class getid3_riff extends getid3_handler {
|
|
428 |
}
|
429 |
if (isset($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO']) && !empty($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) && !empty($thisfile_riff_WAVE['iXML'][0]['timecode_rate'])) {
|
430 |
$samples_since_midnight = floatval(ltrim($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_HI'].$parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO'], '0'));
|
431 |
-
$
|
|
|
432 |
$h = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] / 3600);
|
433 |
$m = floor(($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600)) / 60);
|
434 |
$s = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60));
|
435 |
$f = ($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60) - $s) * $thisfile_riff_WAVE['iXML'][0]['timecode_rate'];
|
436 |
$thisfile_riff_WAVE['iXML'][0]['timecode_string'] = sprintf('%02d:%02d:%02d:%05.2f', $h, $m, $s, $f);
|
437 |
$thisfile_riff_WAVE['iXML'][0]['timecode_string_round'] = sprintf('%02d:%02d:%02d:%02d', $h, $m, $s, round($f));
|
|
|
438 |
}
|
439 |
unset($parsedXML);
|
440 |
}
|
@@ -570,7 +578,7 @@ class getid3_riff extends getid3_handler {
|
|
570 |
// byte, in which case - skip warning
|
571 |
} else {
|
572 |
// Short by more than one byte, throw warning
|
573 |
-
$
|
574 |
$info['avdataend'] = $info['filesize'];
|
575 |
}
|
576 |
break;
|
@@ -579,11 +587,11 @@ class getid3_riff extends getid3_handler {
|
|
579 |
if ((($info['avdataend'] - $info['filesize']) == 1) && (($thisfile_riff[$RIFFsubtype]['data'][0]['size'] % 2) == 0) && ((($info['filesize'] - $info['avdataoffset']) % 2) == 1)) {
|
580 |
// output file appears to be incorrectly *not* padded to nearest WORD boundary
|
581 |
// Output less severe warning
|
582 |
-
$
|
583 |
$info['avdataend'] = $info['filesize'];
|
584 |
} else {
|
585 |
// Short by more than one byte, throw warning
|
586 |
-
$
|
587 |
$info['avdataend'] = $info['filesize'];
|
588 |
}
|
589 |
break;
|
@@ -592,7 +600,7 @@ class getid3_riff extends getid3_handler {
|
|
592 |
if (!empty($info['mpeg']['audio']['LAME']['audio_bytes'])) {
|
593 |
if ((($info['avdataend'] - $info['avdataoffset']) - $info['mpeg']['audio']['LAME']['audio_bytes']) == 1) {
|
594 |
$info['avdataend']--;
|
595 |
-
$
|
596 |
}
|
597 |
}
|
598 |
if (isset($thisfile_audio_dataformat) && ($thisfile_audio_dataformat == 'ac3')) {
|
@@ -611,6 +619,8 @@ class getid3_riff extends getid3_handler {
|
|
611 |
$thisfile_video['bitrate_mode'] = 'vbr'; // maybe not, but probably
|
612 |
$thisfile_video['dataformat'] = 'avi';
|
613 |
|
|
|
|
|
614 |
if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) {
|
615 |
$info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['movi']['offset'] + 8;
|
616 |
if (isset($thisfile_riff['AVIX'])) {
|
@@ -619,7 +629,7 @@ class getid3_riff extends getid3_handler {
|
|
619 |
$info['avdataend'] = $thisfile_riff['AVI ']['movi']['offset'] + $thisfile_riff['AVI ']['movi']['size'];
|
620 |
}
|
621 |
if ($info['avdataend'] > $info['filesize']) {
|
622 |
-
$
|
623 |
$info['avdataend'] = $info['filesize'];
|
624 |
}
|
625 |
}
|
@@ -660,7 +670,7 @@ class getid3_riff extends getid3_handler {
|
|
660 |
|
661 |
$thisfile_riff_raw_avih['dwMicroSecPerFrame'] = $this->EitherEndian2Int(substr($avihData, 0, 4)); // frame display rate (or 0L)
|
662 |
if ($thisfile_riff_raw_avih['dwMicroSecPerFrame'] == 0) {
|
663 |
-
$
|
664 |
return false;
|
665 |
}
|
666 |
|
@@ -693,12 +703,13 @@ class getid3_riff extends getid3_handler {
|
|
693 |
'capturedfile' => 0x00010000,
|
694 |
'copyrighted' => 0x00020010,
|
695 |
);
|
696 |
-
|
697 |
$thisfile_riff_raw_avih['flags'][$flag] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & $value);
|
698 |
}
|
699 |
|
700 |
// shortcut
|
701 |
$thisfile_riff_video[$streamindex] = array();
|
|
|
702 |
$thisfile_riff_video_current = &$thisfile_riff_video[$streamindex];
|
703 |
|
704 |
if ($thisfile_riff_raw_avih['dwWidth'] > 0) {
|
@@ -858,14 +869,14 @@ class getid3_riff extends getid3_handler {
|
|
858 |
break;
|
859 |
|
860 |
default:
|
861 |
-
$
|
862 |
break;
|
863 |
|
864 |
}
|
865 |
}
|
866 |
}
|
867 |
|
868 |
-
if (isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
|
869 |
|
870 |
$thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
|
871 |
if (self::fourccLookup($thisfile_video['fourcc'])) {
|
@@ -912,7 +923,7 @@ class getid3_riff extends getid3_handler {
|
|
912 |
// http://en.wikipedia.org/wiki/CD-DA
|
913 |
case 'CDDA':
|
914 |
$info['fileformat'] = 'cda';
|
915 |
-
|
916 |
|
917 |
$thisfile_audio_dataformat = 'cda';
|
918 |
|
@@ -945,7 +956,7 @@ class getid3_riff extends getid3_handler {
|
|
945 |
}
|
946 |
break;
|
947 |
|
948 |
-
|
949 |
case 'AIFF':
|
950 |
case 'AIFC':
|
951 |
$info['fileformat'] = 'aiff';
|
@@ -963,7 +974,7 @@ class getid3_riff extends getid3_handler {
|
|
963 |
// structures rounded to 2-byte boundary, but dumb encoders
|
964 |
// forget to pad end of file to make this actually work
|
965 |
} else {
|
966 |
-
$
|
967 |
}
|
968 |
$info['avdataend'] = $info['filesize'];
|
969 |
}
|
@@ -1020,7 +1031,7 @@ class getid3_riff extends getid3_handler {
|
|
1020 |
}
|
1021 |
$thisfile_audio['sample_rate'] = $thisfile_riff_audio['sample_rate'];
|
1022 |
if ($thisfile_audio['sample_rate'] == 0) {
|
1023 |
-
$
|
1024 |
return false;
|
1025 |
}
|
1026 |
$info['playtime_seconds'] = $thisfile_riff_audio['total_samples'] / $thisfile_audio['sample_rate'];
|
@@ -1055,7 +1066,7 @@ class getid3_riff extends getid3_handler {
|
|
1055 |
if (isset($thisfile_riff[$RIFFsubtype]['ID3 '])) {
|
1056 |
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
|
1057 |
$getid3_temp = new getID3();
|
1058 |
-
$getid3_temp->openfile($this->getid3->filename);
|
1059 |
$getid3_id3v2 = new getid3_id3v2($getid3_temp);
|
1060 |
$getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['ID3 '][0]['offset'] + 8;
|
1061 |
if ($thisfile_riff[$RIFFsubtype]['ID3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
|
@@ -1075,12 +1086,13 @@ class getid3_riff extends getid3_handler {
|
|
1075 |
$thisfile_audio_dataformat = '8svx';
|
1076 |
$thisfile_audio['bits_per_sample'] = 8;
|
1077 |
$thisfile_audio['channels'] = 1; // overridden below, if need be
|
|
|
1078 |
|
1079 |
if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) {
|
1080 |
$info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8;
|
1081 |
$info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['BODY'][0]['size'];
|
1082 |
if ($info['avdataend'] > $info['filesize']) {
|
1083 |
-
$
|
1084 |
}
|
1085 |
}
|
1086 |
|
@@ -1112,7 +1124,7 @@ class getid3_riff extends getid3_handler {
|
|
1112 |
break;
|
1113 |
|
1114 |
default:
|
1115 |
-
$
|
1116 |
break;
|
1117 |
}
|
1118 |
}
|
@@ -1130,7 +1142,7 @@ class getid3_riff extends getid3_handler {
|
|
1130 |
break;
|
1131 |
|
1132 |
default:
|
1133 |
-
$
|
1134 |
break;
|
1135 |
}
|
1136 |
|
@@ -1157,7 +1169,7 @@ class getid3_riff extends getid3_handler {
|
|
1157 |
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.mpeg.php', __FILE__, true);
|
1158 |
|
1159 |
$getid3_temp = new getID3();
|
1160 |
-
$getid3_temp->openfile($this->getid3->filename);
|
1161 |
$getid3_mpeg = new getid3_mpeg($getid3_temp);
|
1162 |
$getid3_mpeg->Analyze();
|
1163 |
if (empty($getid3_temp->info['error'])) {
|
@@ -1170,9 +1182,59 @@ class getid3_riff extends getid3_handler {
|
|
1170 |
}
|
1171 |
break;
|
1172 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1173 |
|
1174 |
default:
|
1175 |
-
$
|
1176 |
//unset($info['fileformat']);
|
1177 |
}
|
1178 |
|
@@ -1185,7 +1247,7 @@ class getid3_riff extends getid3_handler {
|
|
1185 |
foreach ($ID3v2_keys_bad as $ID3v2_key_bad) {
|
1186 |
if (isset($thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]) && !array_key_exists($ID3v2_key_good, $thisfile_riff[$RIFFsubtype])) {
|
1187 |
$thisfile_riff[$RIFFsubtype][$ID3v2_key_good] = $thisfile_riff[$RIFFsubtype][$ID3v2_key_bad];
|
1188 |
-
$
|
1189 |
}
|
1190 |
}
|
1191 |
|
@@ -1193,7 +1255,7 @@ class getid3_riff extends getid3_handler {
|
|
1193 |
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
|
1194 |
|
1195 |
$getid3_temp = new getID3();
|
1196 |
-
$getid3_temp->openfile($this->getid3->filename);
|
1197 |
$getid3_id3v2 = new getid3_id3v2($getid3_temp);
|
1198 |
$getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['id3 '][0]['offset'] + 8;
|
1199 |
if ($thisfile_riff[$RIFFsubtype]['id3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
|
@@ -1320,6 +1382,15 @@ class getid3_riff extends getid3_handler {
|
|
1320 |
return true;
|
1321 |
}
|
1322 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1323 |
public function ParseRIFFAMV($startoffset, $maxoffset) {
|
1324 |
// AMV files are RIFF-AVI files with parts of the spec deliberately broken, such as chunk size fields hardcoded to zero (because players known in hardware that these fields are always a certain size
|
1325 |
|
@@ -1428,7 +1499,13 @@ class getid3_riff extends getid3_handler {
|
|
1428 |
return $RIFFchunk;
|
1429 |
}
|
1430 |
|
1431 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
1432 |
public function ParseRIFF($startoffset, $maxoffset) {
|
1433 |
$info = &$this->getid3->info;
|
1434 |
|
@@ -1477,7 +1554,7 @@ class getid3_riff extends getid3_handler {
|
|
1477 |
// MP3
|
1478 |
if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) {
|
1479 |
$getid3_temp = new getID3();
|
1480 |
-
$getid3_temp->openfile($this->getid3->filename);
|
1481 |
$getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
|
1482 |
$getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize;
|
1483 |
$getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__);
|
@@ -1499,7 +1576,7 @@ class getid3_riff extends getid3_handler {
|
|
1499 |
|
1500 |
// AC3
|
1501 |
$getid3_temp = new getID3();
|
1502 |
-
$getid3_temp->openfile($this->getid3->filename);
|
1503 |
$getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
|
1504 |
$getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize;
|
1505 |
$getid3_ac3 = new getid3_ac3($getid3_temp);
|
@@ -1509,7 +1586,7 @@ class getid3_riff extends getid3_handler {
|
|
1509 |
$info['ac3'] = $getid3_temp->info['ac3'];
|
1510 |
if (!empty($getid3_temp->info['warning'])) {
|
1511 |
foreach ($getid3_temp->info['warning'] as $key => $value) {
|
1512 |
-
$
|
1513 |
}
|
1514 |
}
|
1515 |
}
|
@@ -1560,7 +1637,7 @@ class getid3_riff extends getid3_handler {
|
|
1560 |
// Probably is MP3 data
|
1561 |
if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($testData, 0, 4))) {
|
1562 |
$getid3_temp = new getID3();
|
1563 |
-
$getid3_temp->openfile($this->getid3->filename);
|
1564 |
$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
|
1565 |
$getid3_temp->info['avdataend'] = $info['avdataend'];
|
1566 |
$getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__);
|
@@ -1577,7 +1654,7 @@ class getid3_riff extends getid3_handler {
|
|
1577 |
// This is probably AC-3 data
|
1578 |
$getid3_temp = new getID3();
|
1579 |
if ($isRegularAC3) {
|
1580 |
-
$getid3_temp->openfile($this->getid3->filename);
|
1581 |
$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
|
1582 |
$getid3_temp->info['avdataend'] = $info['avdataend'];
|
1583 |
}
|
@@ -1611,7 +1688,7 @@ class getid3_riff extends getid3_handler {
|
|
1611 |
|
1612 |
// This is probably DTS data
|
1613 |
$getid3_temp = new getID3();
|
1614 |
-
$getid3_temp->openfile($this->getid3->filename);
|
1615 |
$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
|
1616 |
$getid3_dts = new getid3_dts($getid3_temp);
|
1617 |
$getid3_dts->Analyze();
|
@@ -1680,7 +1757,7 @@ class getid3_riff extends getid3_handler {
|
|
1680 |
// break;
|
1681 |
|
1682 |
default:
|
1683 |
-
if (!empty($LISTchunkParent) && (($RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) {
|
1684 |
$RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
|
1685 |
$RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size'] = $RIFFchunk[$chunkname][$thisindex]['size'];
|
1686 |
unset($RIFFchunk[$chunkname][$thisindex]['offset']);
|
@@ -1715,6 +1792,11 @@ class getid3_riff extends getid3_handler {
|
|
1715 |
return $RIFFchunk;
|
1716 |
}
|
1717 |
|
|
|
|
|
|
|
|
|
|
|
1718 |
public function ParseRIFFdata(&$RIFFdata) {
|
1719 |
$info = &$this->getid3->info;
|
1720 |
if ($RIFFdata) {
|
@@ -1752,6 +1834,12 @@ class getid3_riff extends getid3_handler {
|
|
1752 |
return false;
|
1753 |
}
|
1754 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1755 |
public static function parseComments(&$RIFFinfoArray, &$CommentsTargetArray) {
|
1756 |
$RIFFinfoKeyLookup = array(
|
1757 |
'IARL'=>'archivallocation',
|
@@ -1811,8 +1899,14 @@ class getid3_riff extends getid3_handler {
|
|
1811 |
return true;
|
1812 |
}
|
1813 |
|
|
|
|
|
|
|
|
|
|
|
1814 |
public static function parseWAVEFORMATex($WaveFormatExData) {
|
1815 |
// shortcut
|
|
|
1816 |
$WaveFormatEx['raw'] = array();
|
1817 |
$WaveFormatEx_raw = &$WaveFormatEx['raw'];
|
1818 |
|
@@ -1836,6 +1930,11 @@ class getid3_riff extends getid3_handler {
|
|
1836 |
return $WaveFormatEx;
|
1837 |
}
|
1838 |
|
|
|
|
|
|
|
|
|
|
|
1839 |
public function parseWavPackHeader($WavPackChunkData) {
|
1840 |
// typedef struct {
|
1841 |
// char ckID [4];
|
@@ -1897,6 +1996,12 @@ class getid3_riff extends getid3_handler {
|
|
1897 |
return true;
|
1898 |
}
|
1899 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1900 |
public static function ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true) {
|
1901 |
|
1902 |
$parsed['biSize'] = substr($BITMAPINFOHEADER, 0, 4); // number of bytes required by the BITMAPINFOHEADER structure
|
@@ -1916,6 +2021,12 @@ class getid3_riff extends getid3_handler {
|
|
1916 |
return $parsed;
|
1917 |
}
|
1918 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1919 |
public static function ParseDIVXTAG($DIVXTAG, $raw=false) {
|
1920 |
// structure from "IDivX" source, Form1.frm, by "Greg Frazier of Daemonic Software Group", email: gfrazier@icestorm.net, web: http://dsg.cjb.net/
|
1921 |
// source available at http://files.divx-digest.com/download/c663efe7ef8ad2e90bf4af4d3ea6188a/on0SWN2r/edit/IDivX.zip
|
@@ -1962,6 +2073,7 @@ class getid3_riff extends getid3_handler {
|
|
1962 |
5 => 'NC-17',
|
1963 |
);
|
1964 |
|
|
|
1965 |
$parsed['title'] = trim(substr($DIVXTAG, 0, 32));
|
1966 |
$parsed['artist'] = trim(substr($DIVXTAG, 32, 28));
|
1967 |
$parsed['year'] = intval(trim(substr($DIVXTAG, 60, 4)));
|
@@ -1977,8 +2089,8 @@ class getid3_riff extends getid3_handler {
|
|
1977 |
if (!$raw) {
|
1978 |
unset($parsed['genre_id'], $parsed['rating_id']);
|
1979 |
foreach ($parsed as $key => $value) {
|
1980 |
-
if (
|
1981 |
-
unset($parsed[
|
1982 |
}
|
1983 |
}
|
1984 |
}
|
@@ -1990,6 +2102,11 @@ class getid3_riff extends getid3_handler {
|
|
1990 |
return $parsed;
|
1991 |
}
|
1992 |
|
|
|
|
|
|
|
|
|
|
|
1993 |
public static function waveSNDMtagLookup($tagshortname) {
|
1994 |
$begin = __LINE__;
|
1995 |
|
@@ -2013,6 +2130,11 @@ class getid3_riff extends getid3_handler {
|
|
2013 |
return getid3_lib::EmbeddedLookup($tagshortname, $begin, __LINE__, __FILE__, 'riff-sndm');
|
2014 |
}
|
2015 |
|
|
|
|
|
|
|
|
|
|
|
2016 |
public static function wFormatTagLookup($wFormatTag) {
|
2017 |
|
2018 |
$begin = __LINE__;
|
@@ -2182,6 +2304,11 @@ class getid3_riff extends getid3_handler {
|
|
2182 |
return getid3_lib::EmbeddedLookup('0x'.str_pad(strtoupper(dechex($wFormatTag)), 4, '0', STR_PAD_LEFT), $begin, __LINE__, __FILE__, 'riff-wFormatTag');
|
2183 |
}
|
2184 |
|
|
|
|
|
|
|
|
|
|
|
2185 |
public static function fourccLookup($fourcc) {
|
2186 |
|
2187 |
$begin = __LINE__;
|
@@ -2576,6 +2703,12 @@ class getid3_riff extends getid3_handler {
|
|
2576 |
return getid3_lib::EmbeddedLookup($fourcc, $begin, __LINE__, __FILE__, 'riff-fourcc');
|
2577 |
}
|
2578 |
|
|
|
|
|
|
|
|
|
|
|
|
|
2579 |
private function EitherEndian2Int($byteword, $signed=false) {
|
2580 |
if ($this->container == 'riff') {
|
2581 |
return getid3_lib::LittleEndian2Int($byteword, $signed);
|
@@ -2583,4 +2716,4 @@ class getid3_riff extends getid3_handler {
|
|
2583 |
return getid3_lib::BigEndian2Int($byteword, false, $signed);
|
2584 |
}
|
2585 |
|
2586 |
-
}
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio-video.riff.php //
|
27 |
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ac3.php', __FILE__, true);
|
28 |
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.dts.php', __FILE__, true);
|
29 |
|
30 |
+
class getid3_riff extends getid3_handler
|
31 |
+
{
|
32 |
protected $container = 'riff'; // default
|
33 |
|
34 |
+
/**
|
35 |
+
* @return bool
|
36 |
+
*
|
37 |
+
* @throws getid3_exception
|
38 |
+
*/
|
39 |
public function Analyze() {
|
40 |
$info = &$this->getid3->info;
|
41 |
|
51 |
$thisfile_audio_dataformat = &$thisfile_audio['dataformat'];
|
52 |
$thisfile_riff_audio = &$thisfile_riff['audio'];
|
53 |
$thisfile_riff_video = &$thisfile_riff['video'];
|
54 |
+
$thisfile_riff_WAVE = array();
|
55 |
|
56 |
$Original['avdataoffset'] = $info['avdataoffset'];
|
57 |
$Original['avdataend'] = $info['avdataend'];
|
196 |
$thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($thisfile_riff_WAVE['fmt '][0]['data']);
|
197 |
$thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
|
198 |
if (!isset($thisfile_riff_audio[$streamindex]['bitrate']) || ($thisfile_riff_audio[$streamindex]['bitrate'] == 0)) {
|
199 |
+
$this->error('Corrupt RIFF file: bitrate_audio == zero');
|
200 |
return false;
|
201 |
}
|
202 |
$thisfile_riff_raw['fmt '] = $thisfile_riff_audio[$streamindex]['raw'];
|
205 |
|
206 |
$thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
|
207 |
if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') {
|
208 |
+
$this->warning('Audio codec = '.$thisfile_audio['codec']);
|
209 |
}
|
210 |
$thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
|
211 |
|
308 |
list($dummy, $bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second']) = $matches_bext_time;
|
309 |
$thisfile_riff_WAVE_bext_0['origin_date_unix'] = gmmktime($bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second'], $bext_timestamp['month'], $bext_timestamp['day'], $bext_timestamp['year']);
|
310 |
} else {
|
311 |
+
$this->warning('RIFF.WAVE.BEXT.origin_time is invalid');
|
312 |
}
|
313 |
} else {
|
314 |
+
$this->warning('RIFF.WAVE.BEXT.origin_date is invalid');
|
315 |
}
|
316 |
$thisfile_riff['comments']['author'][] = $thisfile_riff_WAVE_bext_0['author'];
|
317 |
$thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_bext_0['title'];
|
363 |
}
|
364 |
$thisfile_riff_WAVE_cart_0['url'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 748, 1024));
|
365 |
$thisfile_riff_WAVE_cart_0['tag_text'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_cart_0['data'], 1772)));
|
366 |
+
$thisfile_riff['comments']['tag_text'][] = substr($thisfile_riff_WAVE_cart_0['data'], 1772);
|
367 |
|
368 |
$thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist'];
|
369 |
$thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_cart_0['title'];
|
392 |
$SNDM_thisTagOffset += $SNDM_thisTagDataSize;
|
393 |
|
394 |
if ($SNDM_thisTagSize != (4 + 4 + 2 + 2 + $SNDM_thisTagDataSize)) {
|
395 |
+
$this->warning('RIFF.WAVE.SNDM.data contains tag not expected length (expected: '.$SNDM_thisTagSize.', found: '.(4 + 4 + 2 + 2 + $SNDM_thisTagDataSize).') at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')');
|
396 |
break;
|
397 |
} elseif ($SNDM_thisTagSize <= 0) {
|
398 |
+
$this->warning('RIFF.WAVE.SNDM.data contains zero-size tag at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')');
|
399 |
break;
|
400 |
}
|
401 |
$SNDM_startoffset += $SNDM_thisTagSize;
|
404 |
if ($parsedkey = self::waveSNDMtagLookup($SNDM_thisTagKey)) {
|
405 |
$thisfile_riff_WAVE_SNDM_0['parsed'][$parsedkey] = $SNDM_thisTagDataText;
|
406 |
} else {
|
407 |
+
$this->warning('RIFF.WAVE.SNDM contains unknown tag "'.$SNDM_thisTagKey.'" at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')');
|
408 |
}
|
409 |
}
|
410 |
|
412 |
'tracktitle'=>'title',
|
413 |
'category' =>'genre',
|
414 |
'cdtitle' =>'album',
|
|
|
415 |
);
|
416 |
foreach ($tagmapping as $fromkey => $tokey) {
|
417 |
if (isset($thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey])) {
|
434 |
}
|
435 |
if (isset($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO']) && !empty($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) && !empty($thisfile_riff_WAVE['iXML'][0]['timecode_rate'])) {
|
436 |
$samples_since_midnight = floatval(ltrim($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_HI'].$parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO'], '0'));
|
437 |
+
$timestamp_sample_rate = (is_array($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) ? max($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) : $parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']); // XML could possibly contain more than one TIMESTAMP_SAMPLE_RATE tag, returning as array instead of integer [why? does it make sense? perhaps doesn't matter but getID3 needs to deal with it] - see https://github.com/JamesHeinrich/getID3/issues/105
|
438 |
+
$thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] = $samples_since_midnight / $timestamp_sample_rate;
|
439 |
$h = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] / 3600);
|
440 |
$m = floor(($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600)) / 60);
|
441 |
$s = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60));
|
442 |
$f = ($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60) - $s) * $thisfile_riff_WAVE['iXML'][0]['timecode_rate'];
|
443 |
$thisfile_riff_WAVE['iXML'][0]['timecode_string'] = sprintf('%02d:%02d:%02d:%05.2f', $h, $m, $s, $f);
|
444 |
$thisfile_riff_WAVE['iXML'][0]['timecode_string_round'] = sprintf('%02d:%02d:%02d:%02d', $h, $m, $s, round($f));
|
445 |
+
unset($samples_since_midnight, $timestamp_sample_rate, $h, $m, $s, $f);
|
446 |
}
|
447 |
unset($parsedXML);
|
448 |
}
|
578 |
// byte, in which case - skip warning
|
579 |
} else {
|
580 |
// Short by more than one byte, throw warning
|
581 |
+
$this->warning('Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)');
|
582 |
$info['avdataend'] = $info['filesize'];
|
583 |
}
|
584 |
break;
|
587 |
if ((($info['avdataend'] - $info['filesize']) == 1) && (($thisfile_riff[$RIFFsubtype]['data'][0]['size'] % 2) == 0) && ((($info['filesize'] - $info['avdataoffset']) % 2) == 1)) {
|
588 |
// output file appears to be incorrectly *not* padded to nearest WORD boundary
|
589 |
// Output less severe warning
|
590 |
+
$this->warning('File should probably be padded to nearest WORD boundary, but it is not (expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' therefore short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)');
|
591 |
$info['avdataend'] = $info['filesize'];
|
592 |
} else {
|
593 |
// Short by more than one byte, throw warning
|
594 |
+
$this->warning('Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)');
|
595 |
$info['avdataend'] = $info['filesize'];
|
596 |
}
|
597 |
break;
|
600 |
if (!empty($info['mpeg']['audio']['LAME']['audio_bytes'])) {
|
601 |
if ((($info['avdataend'] - $info['avdataoffset']) - $info['mpeg']['audio']['LAME']['audio_bytes']) == 1) {
|
602 |
$info['avdataend']--;
|
603 |
+
$this->warning('Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored');
|
604 |
}
|
605 |
}
|
606 |
if (isset($thisfile_audio_dataformat) && ($thisfile_audio_dataformat == 'ac3')) {
|
619 |
$thisfile_video['bitrate_mode'] = 'vbr'; // maybe not, but probably
|
620 |
$thisfile_video['dataformat'] = 'avi';
|
621 |
|
622 |
+
$thisfile_riff_video_current = array();
|
623 |
+
|
624 |
if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) {
|
625 |
$info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['movi']['offset'] + 8;
|
626 |
if (isset($thisfile_riff['AVIX'])) {
|
629 |
$info['avdataend'] = $thisfile_riff['AVI ']['movi']['offset'] + $thisfile_riff['AVI ']['movi']['size'];
|
630 |
}
|
631 |
if ($info['avdataend'] > $info['filesize']) {
|
632 |
+
$this->warning('Probably truncated file - expecting '.($info['avdataend'] - $info['avdataoffset']).' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($info['avdataend'] - $info['filesize']).' bytes)');
|
633 |
$info['avdataend'] = $info['filesize'];
|
634 |
}
|
635 |
}
|
670 |
|
671 |
$thisfile_riff_raw_avih['dwMicroSecPerFrame'] = $this->EitherEndian2Int(substr($avihData, 0, 4)); // frame display rate (or 0L)
|
672 |
if ($thisfile_riff_raw_avih['dwMicroSecPerFrame'] == 0) {
|
673 |
+
$this->error('Corrupt RIFF file: avih.dwMicroSecPerFrame == zero');
|
674 |
return false;
|
675 |
}
|
676 |
|
703 |
'capturedfile' => 0x00010000,
|
704 |
'copyrighted' => 0x00020010,
|
705 |
);
|
706 |
+
foreach ($flags as $flag => $value) {
|
707 |
$thisfile_riff_raw_avih['flags'][$flag] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & $value);
|
708 |
}
|
709 |
|
710 |
// shortcut
|
711 |
$thisfile_riff_video[$streamindex] = array();
|
712 |
+
/** @var array $thisfile_riff_video_current */
|
713 |
$thisfile_riff_video_current = &$thisfile_riff_video[$streamindex];
|
714 |
|
715 |
if ($thisfile_riff_raw_avih['dwWidth'] > 0) {
|
869 |
break;
|
870 |
|
871 |
default:
|
872 |
+
$this->warning('Unhandled fccType for stream ('.$i.'): "'.$strhfccType.'"');
|
873 |
break;
|
874 |
|
875 |
}
|
876 |
}
|
877 |
}
|
878 |
|
879 |
+
if (isset($thisfile_riff_raw_strf_strhfccType_streamindex) && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
|
880 |
|
881 |
$thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
|
882 |
if (self::fourccLookup($thisfile_video['fourcc'])) {
|
923 |
// http://en.wikipedia.org/wiki/CD-DA
|
924 |
case 'CDDA':
|
925 |
$info['fileformat'] = 'cda';
|
926 |
+
unset($info['mime_type']);
|
927 |
|
928 |
$thisfile_audio_dataformat = 'cda';
|
929 |
|
956 |
}
|
957 |
break;
|
958 |
|
959 |
+
// http://en.wikipedia.org/wiki/AIFF
|
960 |
case 'AIFF':
|
961 |
case 'AIFC':
|
962 |
$info['fileformat'] = 'aiff';
|
974 |
// structures rounded to 2-byte boundary, but dumb encoders
|
975 |
// forget to pad end of file to make this actually work
|
976 |
} else {
|
977 |
+
$this->warning('Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['SSND'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found');
|
978 |
}
|
979 |
$info['avdataend'] = $info['filesize'];
|
980 |
}
|
1031 |
}
|
1032 |
$thisfile_audio['sample_rate'] = $thisfile_riff_audio['sample_rate'];
|
1033 |
if ($thisfile_audio['sample_rate'] == 0) {
|
1034 |
+
$this->error('Corrupted AIFF file: sample_rate == zero');
|
1035 |
return false;
|
1036 |
}
|
1037 |
$info['playtime_seconds'] = $thisfile_riff_audio['total_samples'] / $thisfile_audio['sample_rate'];
|
1066 |
if (isset($thisfile_riff[$RIFFsubtype]['ID3 '])) {
|
1067 |
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
|
1068 |
$getid3_temp = new getID3();
|
1069 |
+
$getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
|
1070 |
$getid3_id3v2 = new getid3_id3v2($getid3_temp);
|
1071 |
$getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['ID3 '][0]['offset'] + 8;
|
1072 |
if ($thisfile_riff[$RIFFsubtype]['ID3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
|
1086 |
$thisfile_audio_dataformat = '8svx';
|
1087 |
$thisfile_audio['bits_per_sample'] = 8;
|
1088 |
$thisfile_audio['channels'] = 1; // overridden below, if need be
|
1089 |
+
$ActualBitsPerSample = 0;
|
1090 |
|
1091 |
if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) {
|
1092 |
$info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8;
|
1093 |
$info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['BODY'][0]['size'];
|
1094 |
if ($info['avdataend'] > $info['filesize']) {
|
1095 |
+
$this->warning('Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['BODY'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found');
|
1096 |
}
|
1097 |
}
|
1098 |
|
1124 |
break;
|
1125 |
|
1126 |
default:
|
1127 |
+
$this->warning('Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.$thisfile_riff_RIFFsubtype_VHDR_0['sCompression'].'"');
|
1128 |
break;
|
1129 |
}
|
1130 |
}
|
1142 |
break;
|
1143 |
|
1144 |
default:
|
1145 |
+
$this->warning('Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "'.$ChannelsIndex.'"');
|
1146 |
break;
|
1147 |
}
|
1148 |
|
1169 |
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.mpeg.php', __FILE__, true);
|
1170 |
|
1171 |
$getid3_temp = new getID3();
|
1172 |
+
$getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
|
1173 |
$getid3_mpeg = new getid3_mpeg($getid3_temp);
|
1174 |
$getid3_mpeg->Analyze();
|
1175 |
if (empty($getid3_temp->info['error'])) {
|
1182 |
}
|
1183 |
break;
|
1184 |
|
1185 |
+
case 'WEBP':
|
1186 |
+
// https://developers.google.com/speed/webp/docs/riff_container
|
1187 |
+
// https://tools.ietf.org/html/rfc6386
|
1188 |
+
// https://chromium.googlesource.com/webm/libwebp/+/master/doc/webp-lossless-bitstream-spec.txt
|
1189 |
+
$info['fileformat'] = 'webp';
|
1190 |
+
$info['mime_type'] = 'image/webp';
|
1191 |
+
|
1192 |
+
if (!empty($thisfile_riff['WEBP']['VP8 '][0]['size'])) {
|
1193 |
+
$old_offset = $this->ftell();
|
1194 |
+
$this->fseek($thisfile_riff['WEBP']['VP8 '][0]['offset'] + 8); // 4 bytes "VP8 " + 4 bytes chunk size
|
1195 |
+
$WEBP_VP8_header = $this->fread(10);
|
1196 |
+
$this->fseek($old_offset);
|
1197 |
+
if (substr($WEBP_VP8_header, 3, 3) == "\x9D\x01\x2A") {
|
1198 |
+
$thisfile_riff['WEBP']['VP8 '][0]['keyframe'] = !(getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x800000);
|
1199 |
+
$thisfile_riff['WEBP']['VP8 '][0]['version'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x700000) >> 20;
|
1200 |
+
$thisfile_riff['WEBP']['VP8 '][0]['show_frame'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x080000);
|
1201 |
+
$thisfile_riff['WEBP']['VP8 '][0]['data_bytes'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x07FFFF) >> 0;
|
1202 |
+
|
1203 |
+
$thisfile_riff['WEBP']['VP8 '][0]['scale_x'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0xC000) >> 14;
|
1204 |
+
$thisfile_riff['WEBP']['VP8 '][0]['width'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0x3FFF);
|
1205 |
+
$thisfile_riff['WEBP']['VP8 '][0]['scale_y'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0xC000) >> 14;
|
1206 |
+
$thisfile_riff['WEBP']['VP8 '][0]['height'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0x3FFF);
|
1207 |
+
|
1208 |
+
$info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8 '][0]['width'];
|
1209 |
+
$info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8 '][0]['height'];
|
1210 |
+
} else {
|
1211 |
+
$this->error('Expecting 9D 01 2A at offset '.($thisfile_riff['WEBP']['VP8 '][0]['offset'] + 8 + 3).', found "'.getid3_lib::PrintHexBytes(substr($WEBP_VP8_header, 3, 3)).'"');
|
1212 |
+
}
|
1213 |
+
|
1214 |
+
}
|
1215 |
+
if (!empty($thisfile_riff['WEBP']['VP8L'][0]['size'])) {
|
1216 |
+
$old_offset = $this->ftell();
|
1217 |
+
$this->fseek($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8); // 4 bytes "VP8L" + 4 bytes chunk size
|
1218 |
+
$WEBP_VP8L_header = $this->fread(10);
|
1219 |
+
$this->fseek($old_offset);
|
1220 |
+
if (substr($WEBP_VP8L_header, 0, 1) == "\x2F") {
|
1221 |
+
$width_height_flags = getid3_lib::LittleEndian2Bin(substr($WEBP_VP8L_header, 1, 4));
|
1222 |
+
$thisfile_riff['WEBP']['VP8L'][0]['width'] = bindec(substr($width_height_flags, 18, 14)) + 1;
|
1223 |
+
$thisfile_riff['WEBP']['VP8L'][0]['height'] = bindec(substr($width_height_flags, 4, 14)) + 1;
|
1224 |
+
$thisfile_riff['WEBP']['VP8L'][0]['alpha_is_used'] = (bool) bindec(substr($width_height_flags, 3, 1));
|
1225 |
+
$thisfile_riff['WEBP']['VP8L'][0]['version'] = bindec(substr($width_height_flags, 0, 3));
|
1226 |
+
|
1227 |
+
$info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8L'][0]['width'];
|
1228 |
+
$info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8L'][0]['height'];
|
1229 |
+
} else {
|
1230 |
+
$this->error('Expecting 2F at offset '.($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8).', found "'.getid3_lib::PrintHexBytes(substr($WEBP_VP8L_header, 0, 1)).'"');
|
1231 |
+
}
|
1232 |
+
|
1233 |
+
}
|
1234 |
+
break;
|
1235 |
|
1236 |
default:
|
1237 |
+
$this->error('Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA|WEBP), found "'.$RIFFsubtype.'" instead');
|
1238 |
//unset($info['fileformat']);
|
1239 |
}
|
1240 |
|
1247 |
foreach ($ID3v2_keys_bad as $ID3v2_key_bad) {
|
1248 |
if (isset($thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]) && !array_key_exists($ID3v2_key_good, $thisfile_riff[$RIFFsubtype])) {
|
1249 |
$thisfile_riff[$RIFFsubtype][$ID3v2_key_good] = $thisfile_riff[$RIFFsubtype][$ID3v2_key_bad];
|
1250 |
+
$this->warning('mapping "'.$ID3v2_key_bad.'" chunk to "'.$ID3v2_key_good.'"');
|
1251 |
}
|
1252 |
}
|
1253 |
|
1255 |
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
|
1256 |
|
1257 |
$getid3_temp = new getID3();
|
1258 |
+
$getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
|
1259 |
$getid3_id3v2 = new getid3_id3v2($getid3_temp);
|
1260 |
$getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['id3 '][0]['offset'] + 8;
|
1261 |
if ($thisfile_riff[$RIFFsubtype]['id3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
|
1382 |
return true;
|
1383 |
}
|
1384 |
|
1385 |
+
/**
|
1386 |
+
* @param int $startoffset
|
1387 |
+
* @param int $maxoffset
|
1388 |
+
*
|
1389 |
+
* @return array|false
|
1390 |
+
*
|
1391 |
+
* @throws Exception
|
1392 |
+
* @throws getid3_exception
|
1393 |
+
*/
|
1394 |
public function ParseRIFFAMV($startoffset, $maxoffset) {
|
1395 |
// AMV files are RIFF-AVI files with parts of the spec deliberately broken, such as chunk size fields hardcoded to zero (because players known in hardware that these fields are always a certain size
|
1396 |
|
1499 |
return $RIFFchunk;
|
1500 |
}
|
1501 |
|
1502 |
+
/**
|
1503 |
+
* @param int $startoffset
|
1504 |
+
* @param int $maxoffset
|
1505 |
+
*
|
1506 |
+
* @return array|false
|
1507 |
+
* @throws getid3_exception
|
1508 |
+
*/
|
1509 |
public function ParseRIFF($startoffset, $maxoffset) {
|
1510 |
$info = &$this->getid3->info;
|
1511 |
|
1554 |
// MP3
|
1555 |
if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) {
|
1556 |
$getid3_temp = new getID3();
|
1557 |
+
$getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
|
1558 |
$getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
|
1559 |
$getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize;
|
1560 |
$getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__);
|
1576 |
|
1577 |
// AC3
|
1578 |
$getid3_temp = new getID3();
|
1579 |
+
$getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
|
1580 |
$getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
|
1581 |
$getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize;
|
1582 |
$getid3_ac3 = new getid3_ac3($getid3_temp);
|
1586 |
$info['ac3'] = $getid3_temp->info['ac3'];
|
1587 |
if (!empty($getid3_temp->info['warning'])) {
|
1588 |
foreach ($getid3_temp->info['warning'] as $key => $value) {
|
1589 |
+
$this->warning($value);
|
1590 |
}
|
1591 |
}
|
1592 |
}
|
1637 |
// Probably is MP3 data
|
1638 |
if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($testData, 0, 4))) {
|
1639 |
$getid3_temp = new getID3();
|
1640 |
+
$getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
|
1641 |
$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
|
1642 |
$getid3_temp->info['avdataend'] = $info['avdataend'];
|
1643 |
$getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__);
|
1654 |
// This is probably AC-3 data
|
1655 |
$getid3_temp = new getID3();
|
1656 |
if ($isRegularAC3) {
|
1657 |
+
$getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
|
1658 |
$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
|
1659 |
$getid3_temp->info['avdataend'] = $info['avdataend'];
|
1660 |
}
|
1688 |
|
1689 |
// This is probably DTS data
|
1690 |
$getid3_temp = new getID3();
|
1691 |
+
$getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
|
1692 |
$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
|
1693 |
$getid3_dts = new getid3_dts($getid3_temp);
|
1694 |
$getid3_dts->Analyze();
|
1757 |
// break;
|
1758 |
|
1759 |
default:
|
1760 |
+
if (!empty($LISTchunkParent) && isset($LISTchunkMaxOffset) && (($RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) {
|
1761 |
$RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
|
1762 |
$RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size'] = $RIFFchunk[$chunkname][$thisindex]['size'];
|
1763 |
unset($RIFFchunk[$chunkname][$thisindex]['offset']);
|
1792 |
return $RIFFchunk;
|
1793 |
}
|
1794 |
|
1795 |
+
/**
|
1796 |
+
* @param string $RIFFdata
|
1797 |
+
*
|
1798 |
+
* @return bool
|
1799 |
+
*/
|
1800 |
public function ParseRIFFdata(&$RIFFdata) {
|
1801 |
$info = &$this->getid3->info;
|
1802 |
if ($RIFFdata) {
|
1834 |
return false;
|
1835 |
}
|
1836 |
|
1837 |
+
/**
|
1838 |
+
* @param array $RIFFinfoArray
|
1839 |
+
* @param array $CommentsTargetArray
|
1840 |
+
*
|
1841 |
+
* @return bool
|
1842 |
+
*/
|
1843 |
public static function parseComments(&$RIFFinfoArray, &$CommentsTargetArray) {
|
1844 |
$RIFFinfoKeyLookup = array(
|
1845 |
'IARL'=>'archivallocation',
|
1899 |
return true;
|
1900 |
}
|
1901 |
|
1902 |
+
/**
|
1903 |
+
* @param string $WaveFormatExData
|
1904 |
+
*
|
1905 |
+
* @return array
|
1906 |
+
*/
|
1907 |
public static function parseWAVEFORMATex($WaveFormatExData) {
|
1908 |
// shortcut
|
1909 |
+
$WaveFormatEx = array();
|
1910 |
$WaveFormatEx['raw'] = array();
|
1911 |
$WaveFormatEx_raw = &$WaveFormatEx['raw'];
|
1912 |
|
1930 |
return $WaveFormatEx;
|
1931 |
}
|
1932 |
|
1933 |
+
/**
|
1934 |
+
* @param string $WavPackChunkData
|
1935 |
+
*
|
1936 |
+
* @return bool
|
1937 |
+
*/
|
1938 |
public function parseWavPackHeader($WavPackChunkData) {
|
1939 |
// typedef struct {
|
1940 |
// char ckID [4];
|
1996 |
return true;
|
1997 |
}
|
1998 |
|
1999 |
+
/**
|
2000 |
+
* @param string $BITMAPINFOHEADER
|
2001 |
+
* @param bool $littleEndian
|
2002 |
+
*
|
2003 |
+
* @return array
|
2004 |
+
*/
|
2005 |
public static function ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true) {
|
2006 |
|
2007 |
$parsed['biSize'] = substr($BITMAPINFOHEADER, 0, 4); // number of bytes required by the BITMAPINFOHEADER structure
|
2021 |
return $parsed;
|
2022 |
}
|
2023 |
|
2024 |
+
/**
|
2025 |
+
* @param string $DIVXTAG
|
2026 |
+
* @param bool $raw
|
2027 |
+
*
|
2028 |
+
* @return array
|
2029 |
+
*/
|
2030 |
public static function ParseDIVXTAG($DIVXTAG, $raw=false) {
|
2031 |
// structure from "IDivX" source, Form1.frm, by "Greg Frazier of Daemonic Software Group", email: gfrazier@icestorm.net, web: http://dsg.cjb.net/
|
2032 |
// source available at http://files.divx-digest.com/download/c663efe7ef8ad2e90bf4af4d3ea6188a/on0SWN2r/edit/IDivX.zip
|
2073 |
5 => 'NC-17',
|
2074 |
);
|
2075 |
|
2076 |
+
$parsed = array();
|
2077 |
$parsed['title'] = trim(substr($DIVXTAG, 0, 32));
|
2078 |
$parsed['artist'] = trim(substr($DIVXTAG, 32, 28));
|
2079 |
$parsed['year'] = intval(trim(substr($DIVXTAG, 60, 4)));
|
2089 |
if (!$raw) {
|
2090 |
unset($parsed['genre_id'], $parsed['rating_id']);
|
2091 |
foreach ($parsed as $key => $value) {
|
2092 |
+
if (empty($value)) {
|
2093 |
+
unset($parsed[$key]);
|
2094 |
}
|
2095 |
}
|
2096 |
}
|
2102 |
return $parsed;
|
2103 |
}
|
2104 |
|
2105 |
+
/**
|
2106 |
+
* @param string $tagshortname
|
2107 |
+
*
|
2108 |
+
* @return string
|
2109 |
+
*/
|
2110 |
public static function waveSNDMtagLookup($tagshortname) {
|
2111 |
$begin = __LINE__;
|
2112 |
|
2130 |
return getid3_lib::EmbeddedLookup($tagshortname, $begin, __LINE__, __FILE__, 'riff-sndm');
|
2131 |
}
|
2132 |
|
2133 |
+
/**
|
2134 |
+
* @param int $wFormatTag
|
2135 |
+
*
|
2136 |
+
* @return string
|
2137 |
+
*/
|
2138 |
public static function wFormatTagLookup($wFormatTag) {
|
2139 |
|
2140 |
$begin = __LINE__;
|
2304 |
return getid3_lib::EmbeddedLookup('0x'.str_pad(strtoupper(dechex($wFormatTag)), 4, '0', STR_PAD_LEFT), $begin, __LINE__, __FILE__, 'riff-wFormatTag');
|
2305 |
}
|
2306 |
|
2307 |
+
/**
|
2308 |
+
* @param string $fourcc
|
2309 |
+
*
|
2310 |
+
* @return string
|
2311 |
+
*/
|
2312 |
public static function fourccLookup($fourcc) {
|
2313 |
|
2314 |
$begin = __LINE__;
|
2703 |
return getid3_lib::EmbeddedLookup($fourcc, $begin, __LINE__, __FILE__, 'riff-fourcc');
|
2704 |
}
|
2705 |
|
2706 |
+
/**
|
2707 |
+
* @param string $byteword
|
2708 |
+
* @param bool $signed
|
2709 |
+
*
|
2710 |
+
* @return int|float|false
|
2711 |
+
*/
|
2712 |
private function EitherEndian2Int($byteword, $signed=false) {
|
2713 |
if ($this->container == 'riff') {
|
2714 |
return getid3_lib::LittleEndian2Int($byteword, $signed);
|
2716 |
return getid3_lib::BigEndian2Int($byteword, false, $signed);
|
2717 |
}
|
2718 |
|
2719 |
+
}
|
lib/getid3/module.audio-video.swf.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio-video.swf.php //
|
@@ -19,6 +19,9 @@ class getid3_swf extends getid3_handler
|
|
19 |
{
|
20 |
public $ReturnAllTagData = false;
|
21 |
|
|
|
|
|
|
|
22 |
public function Analyze() {
|
23 |
$info = &$this->getid3->info;
|
24 |
|
@@ -42,7 +45,7 @@ class getid3_swf extends getid3_handler
|
|
42 |
break;
|
43 |
|
44 |
default:
|
45 |
-
$
|
46 |
unset($info['swf']);
|
47 |
unset($info['fileformat']);
|
48 |
return false;
|
@@ -57,7 +60,7 @@ class getid3_swf extends getid3_handler
|
|
57 |
if ($decompressed = @gzuncompress($SWFfileData)) {
|
58 |
$SWFfileData = $SWFHead.$decompressed;
|
59 |
} else {
|
60 |
-
$
|
61 |
return false;
|
62 |
}
|
63 |
}
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio-video.swf.php //
|
19 |
{
|
20 |
public $ReturnAllTagData = false;
|
21 |
|
22 |
+
/**
|
23 |
+
* @return bool
|
24 |
+
*/
|
25 |
public function Analyze() {
|
26 |
$info = &$this->getid3->info;
|
27 |
|
45 |
break;
|
46 |
|
47 |
default:
|
48 |
+
$this->error('Expecting "FWS" or "CWS" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($info['swf']['header']['signature']).'"');
|
49 |
unset($info['swf']);
|
50 |
unset($info['fileformat']);
|
51 |
return false;
|
60 |
if ($decompressed = @gzuncompress($SWFfileData)) {
|
61 |
$SWFfileData = $SWFHead.$decompressed;
|
62 |
} else {
|
63 |
+
$this->error('Error decompressing compressed SWF data ('.strlen($SWFfileData).' bytes compressed, should be '.($info['swf']['header']['length'] - 8).' bytes uncompressed)');
|
64 |
return false;
|
65 |
}
|
66 |
}
|
lib/getid3/module.audio-video.ts.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio-video.ts.php //
|
@@ -17,7 +17,9 @@
|
|
17 |
|
18 |
class getid3_ts extends getid3_handler
|
19 |
{
|
20 |
-
|
|
|
|
|
21 |
public function Analyze() {
|
22 |
$info = &$this->getid3->info;
|
23 |
|
@@ -25,7 +27,7 @@ class getid3_ts extends getid3_handler
|
|
25 |
$TSheader = $this->fread(19);
|
26 |
$magic = "\x47";
|
27 |
if (substr($TSheader, 0, 1) != $magic) {
|
28 |
-
$
|
29 |
return false;
|
30 |
}
|
31 |
$info['fileformat'] = 'ts';
|
@@ -66,12 +68,16 @@ class getid3_ts extends getid3_handler
|
|
66 |
}
|
67 |
}
|
68 |
|
69 |
-
$
|
70 |
-
return false;
|
71 |
|
72 |
}
|
73 |
|
74 |
-
|
|
|
|
|
|
|
|
|
75 |
public function TSscramblingControlLookup($raw) {
|
76 |
$TSscramblingControlLookup = array(0x00=>'not scrambled', 0x01=>'reserved', 0x02=>'scrambled, even key', 0x03=>'scrambled, odd key');
|
77 |
return (isset($TSscramblingControlLookup[$raw]) ? $TSscramblingControlLookup[$raw] : 'invalid');
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio-video.ts.php //
|
17 |
|
18 |
class getid3_ts extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @return bool
|
22 |
+
*/
|
23 |
public function Analyze() {
|
24 |
$info = &$this->getid3->info;
|
25 |
|
27 |
$TSheader = $this->fread(19);
|
28 |
$magic = "\x47";
|
29 |
if (substr($TSheader, 0, 1) != $magic) {
|
30 |
+
$this->error('Expecting "'.getid3_lib::PrintHexBytes($magic).'" at '.$info['avdataoffset'].', found '.getid3_lib::PrintHexBytes(substr($TSheader, 0, 1)).' instead.');
|
31 |
return false;
|
32 |
}
|
33 |
$info['fileformat'] = 'ts';
|
68 |
}
|
69 |
}
|
70 |
|
71 |
+
$this->error('MPEG Transport Stream (.ts) parsing not enabled in this version of getID3() ['.$this->getid3->version().']');
|
72 |
+
return false;
|
73 |
|
74 |
}
|
75 |
|
76 |
+
/**
|
77 |
+
* @param int $raw
|
78 |
+
*
|
79 |
+
* @return string
|
80 |
+
*/
|
81 |
public function TSscramblingControlLookup($raw) {
|
82 |
$TSscramblingControlLookup = array(0x00=>'not scrambled', 0x01=>'reserved', 0x02=>'scrambled, even key', 0x03=>'scrambled, odd key');
|
83 |
return (isset($TSscramblingControlLookup[$raw]) ? $TSscramblingControlLookup[$raw] : 'invalid');
|
lib/getid3/module.audio.aa.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.aa.php //
|
@@ -17,7 +17,9 @@
|
|
17 |
|
18 |
class getid3_aa extends getid3_handler
|
19 |
{
|
20 |
-
|
|
|
|
|
21 |
public function Analyze() {
|
22 |
$info = &$this->getid3->info;
|
23 |
|
@@ -26,7 +28,7 @@ class getid3_aa extends getid3_handler
|
|
26 |
|
27 |
$magic = "\x57\x90\x75\x36";
|
28 |
if (substr($AAheader, 4, 4) != $magic) {
|
29 |
-
$
|
30 |
return false;
|
31 |
}
|
32 |
|
@@ -36,14 +38,14 @@ class getid3_aa extends getid3_handler
|
|
36 |
|
37 |
$info['fileformat'] = 'aa';
|
38 |
$info['audio']['dataformat'] = 'aa';
|
39 |
-
$
|
40 |
-
return false;
|
41 |
$info['audio']['bitrate_mode'] = 'cbr'; // is it?
|
42 |
$thisfile_aa['encoding'] = 'ISO-8859-1';
|
43 |
|
44 |
-
$thisfile_aa['filesize'] = getid3_lib::BigEndian2Int(substr($
|
45 |
if ($thisfile_aa['filesize'] > ($info['avdataend'] - $info['avdataoffset'])) {
|
46 |
-
$
|
47 |
}
|
48 |
|
49 |
$info['audio']['bits_per_sample'] = 16; // is it?
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.aa.php //
|
17 |
|
18 |
class getid3_aa extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @return bool
|
22 |
+
*/
|
23 |
public function Analyze() {
|
24 |
$info = &$this->getid3->info;
|
25 |
|
28 |
|
29 |
$magic = "\x57\x90\x75\x36";
|
30 |
if (substr($AAheader, 4, 4) != $magic) {
|
31 |
+
$this->error('Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($AAheader, 4, 4)).'"');
|
32 |
return false;
|
33 |
}
|
34 |
|
38 |
|
39 |
$info['fileformat'] = 'aa';
|
40 |
$info['audio']['dataformat'] = 'aa';
|
41 |
+
$this->error('Audible Audiobook (.aa) parsing not enabled in this version of getID3() ['.$this->getid3->version().']');
|
42 |
+
return false;
|
43 |
$info['audio']['bitrate_mode'] = 'cbr'; // is it?
|
44 |
$thisfile_aa['encoding'] = 'ISO-8859-1';
|
45 |
|
46 |
+
$thisfile_aa['filesize'] = getid3_lib::BigEndian2Int(substr($AAheader, 0, 4));
|
47 |
if ($thisfile_aa['filesize'] > ($info['avdataend'] - $info['avdataoffset'])) {
|
48 |
+
$this->warning('Possible truncated file - expecting "'.$thisfile_aa['filesize'].'" bytes of data, only found '.($info['avdataend'] - $info['avdataoffset']).' bytes"');
|
49 |
}
|
50 |
|
51 |
$info['audio']['bits_per_sample'] = 16; // is it?
|
lib/getid3/module.audio.aac.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.aac.php //
|
@@ -17,6 +17,9 @@
|
|
17 |
|
18 |
class getid3_aac extends getid3_handler
|
19 |
{
|
|
|
|
|
|
|
20 |
public function Analyze() {
|
21 |
$info = &$this->getid3->info;
|
22 |
$this->fseek($info['avdataoffset']);
|
@@ -28,8 +31,9 @@ class getid3_aac extends getid3_handler
|
|
28 |
return true;
|
29 |
}
|
30 |
|
31 |
-
|
32 |
-
|
|
|
33 |
public function getAACADIFheaderFilepointer() {
|
34 |
$info = &$this->getid3->info;
|
35 |
$info['fileformat'] = 'aac';
|
@@ -69,17 +73,17 @@ class getid3_aac extends getid3_handler
|
|
69 |
$bitoffset += 32;
|
70 |
$info['aac']['header']['mpeg_version'] = 4;
|
71 |
|
72 |
-
$info['aac']['header']['copyright'] =
|
73 |
$bitoffset += 1;
|
74 |
if ($info['aac']['header']['copyright']) {
|
75 |
$info['aac']['header']['copyright_id'] = getid3_lib::Bin2String(substr($AACheaderBitstream, $bitoffset, 72));
|
76 |
$bitoffset += 72;
|
77 |
}
|
78 |
-
$info['aac']['header']['original_copy'] =
|
79 |
$bitoffset += 1;
|
80 |
-
$info['aac']['header']['home'] =
|
81 |
$bitoffset += 1;
|
82 |
-
$info['aac']['header']['is_vbr'] =
|
83 |
$bitoffset += 1;
|
84 |
if ($info['aac']['header']['is_vbr']) {
|
85 |
$info['audio']['bitrate_mode'] = 'vbr';
|
@@ -92,7 +96,7 @@ class getid3_aac extends getid3_handler
|
|
92 |
$info['audio']['bitrate'] = $info['aac']['header']['bitrate'];
|
93 |
}
|
94 |
if ($info['audio']['bitrate'] == 0) {
|
95 |
-
$
|
96 |
return false;
|
97 |
}
|
98 |
$info['aac']['header']['num_program_configs'] = 1 + getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
|
@@ -250,14 +254,19 @@ class getid3_aac extends getid3_handler
|
|
250 |
|
251 |
unset($info['fileformat']);
|
252 |
unset($info['aac']);
|
253 |
-
$
|
254 |
return false;
|
255 |
|
256 |
}
|
257 |
|
258 |
}
|
259 |
|
260 |
-
|
|
|
|
|
|
|
|
|
|
|
261 |
public function getAACADTSheaderFilepointer($MaxFramesToScan=1000000, $ReturnExtendedInfo=false) {
|
262 |
$info = &$this->getid3->info;
|
263 |
|
@@ -311,7 +320,7 @@ class getid3_aac extends getid3_handler
|
|
311 |
// or MaxFramesToScan frames have been scanned
|
312 |
|
313 |
if (!getid3_lib::intValueSupported($byteoffset)) {
|
314 |
-
$
|
315 |
return false;
|
316 |
}
|
317 |
$this->fseek($byteoffset);
|
@@ -320,7 +329,7 @@ class getid3_aac extends getid3_handler
|
|
320 |
$substring = $this->fread(9); // header is 7 bytes (or 9 if CRC is present)
|
321 |
$substringlength = strlen($substring);
|
322 |
if ($substringlength != 9) {
|
323 |
-
$
|
324 |
return false;
|
325 |
}
|
326 |
// this would be easier with 64-bit math, but split it up to allow for 32-bit:
|
@@ -330,7 +339,7 @@ class getid3_aac extends getid3_handler
|
|
330 |
|
331 |
$info['aac']['header']['raw']['syncword'] = ($header1 & 0xFFF0) >> 4;
|
332 |
if ($info['aac']['header']['raw']['syncword'] != 0x0FFF) {
|
333 |
-
$
|
334 |
//if ($info['fileformat'] == 'aac') {
|
335 |
// return true;
|
336 |
//}
|
@@ -372,10 +381,10 @@ class getid3_aac extends getid3_handler
|
|
372 |
}
|
373 |
|
374 |
if ($info['aac']['header']['raw']['mpeg_layer'] != 0) {
|
375 |
-
$
|
376 |
}
|
377 |
if ($info['aac']['header']['sample_frequency'] == 0) {
|
378 |
-
$
|
379 |
return false;
|
380 |
}
|
381 |
|
@@ -428,7 +437,7 @@ class getid3_aac extends getid3_handler
|
|
428 |
$info['aac']['frames'] = $framenumber;
|
429 |
$info['playtime_seconds'] = ($info['avdataend'] / $byteoffset) * (($framenumber * 1024) / $info['aac']['header']['sample_frequency']); // (1 / % of file scanned) * (samples / (samples/sec)) = seconds
|
430 |
if ($info['playtime_seconds'] == 0) {
|
431 |
-
$
|
432 |
return false;
|
433 |
}
|
434 |
$info['audio']['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
|
@@ -443,6 +452,11 @@ class getid3_aac extends getid3_handler
|
|
443 |
// should never get here.
|
444 |
}
|
445 |
|
|
|
|
|
|
|
|
|
|
|
446 |
public static function AACsampleRateLookup($samplerateid) {
|
447 |
static $AACsampleRateLookup = array();
|
448 |
if (empty($AACsampleRateLookup)) {
|
@@ -466,6 +480,12 @@ class getid3_aac extends getid3_handler
|
|
466 |
return (isset($AACsampleRateLookup[$samplerateid]) ? $AACsampleRateLookup[$samplerateid] : 'invalid');
|
467 |
}
|
468 |
|
|
|
|
|
|
|
|
|
|
|
|
|
469 |
public static function AACprofileLookup($profileid, $mpegversion) {
|
470 |
static $AACprofileLookup = array();
|
471 |
if (empty($AACprofileLookup)) {
|
@@ -481,6 +501,11 @@ class getid3_aac extends getid3_handler
|
|
481 |
return (isset($AACprofileLookup[$mpegversion][$profileid]) ? $AACprofileLookup[$mpegversion][$profileid] : 'invalid');
|
482 |
}
|
483 |
|
|
|
|
|
|
|
|
|
|
|
484 |
public static function AACchannelCountCalculate($program_configs) {
|
485 |
$channels = 0;
|
486 |
for ($i = 0; $i < $program_configs['num_front_channel_elements']; $i++) {
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.aac.php //
|
17 |
|
18 |
class getid3_aac extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @return bool
|
22 |
+
*/
|
23 |
public function Analyze() {
|
24 |
$info = &$this->getid3->info;
|
25 |
$this->fseek($info['avdataoffset']);
|
31 |
return true;
|
32 |
}
|
33 |
|
34 |
+
/**
|
35 |
+
* @return bool
|
36 |
+
*/
|
37 |
public function getAACADIFheaderFilepointer() {
|
38 |
$info = &$this->getid3->info;
|
39 |
$info['fileformat'] = 'aac';
|
73 |
$bitoffset += 32;
|
74 |
$info['aac']['header']['mpeg_version'] = 4;
|
75 |
|
76 |
+
$info['aac']['header']['copyright'] = substr($AACheaderBitstream, $bitoffset, 1) == '1';
|
77 |
$bitoffset += 1;
|
78 |
if ($info['aac']['header']['copyright']) {
|
79 |
$info['aac']['header']['copyright_id'] = getid3_lib::Bin2String(substr($AACheaderBitstream, $bitoffset, 72));
|
80 |
$bitoffset += 72;
|
81 |
}
|
82 |
+
$info['aac']['header']['original_copy'] = substr($AACheaderBitstream, $bitoffset, 1) == '1';
|
83 |
$bitoffset += 1;
|
84 |
+
$info['aac']['header']['home'] = substr($AACheaderBitstream, $bitoffset, 1) == '1';
|
85 |
$bitoffset += 1;
|
86 |
+
$info['aac']['header']['is_vbr'] = substr($AACheaderBitstream, $bitoffset, 1) == '1';
|
87 |
$bitoffset += 1;
|
88 |
if ($info['aac']['header']['is_vbr']) {
|
89 |
$info['audio']['bitrate_mode'] = 'vbr';
|
96 |
$info['audio']['bitrate'] = $info['aac']['header']['bitrate'];
|
97 |
}
|
98 |
if ($info['audio']['bitrate'] == 0) {
|
99 |
+
$this->error('Corrupt AAC file: bitrate_audio == zero');
|
100 |
return false;
|
101 |
}
|
102 |
$info['aac']['header']['num_program_configs'] = 1 + getid3_lib::Bin2Dec(substr($AACheaderBitstream, $bitoffset, 4));
|
254 |
|
255 |
unset($info['fileformat']);
|
256 |
unset($info['aac']);
|
257 |
+
$this->error('AAC-ADIF synch not found at offset '.$info['avdataoffset'].' (expected "ADIF", found "'.substr($AACheader, 0, 4).'" instead)');
|
258 |
return false;
|
259 |
|
260 |
}
|
261 |
|
262 |
}
|
263 |
|
264 |
+
/**
|
265 |
+
* @param int $MaxFramesToScan
|
266 |
+
* @param bool $ReturnExtendedInfo
|
267 |
+
*
|
268 |
+
* @return bool
|
269 |
+
*/
|
270 |
public function getAACADTSheaderFilepointer($MaxFramesToScan=1000000, $ReturnExtendedInfo=false) {
|
271 |
$info = &$this->getid3->info;
|
272 |
|
320 |
// or MaxFramesToScan frames have been scanned
|
321 |
|
322 |
if (!getid3_lib::intValueSupported($byteoffset)) {
|
323 |
+
$this->warning('Unable to parse AAC file beyond '.$this->ftell().' (PHP does not support file operations beyond '.round(PHP_INT_MAX / 1073741824).'GB)');
|
324 |
return false;
|
325 |
}
|
326 |
$this->fseek($byteoffset);
|
329 |
$substring = $this->fread(9); // header is 7 bytes (or 9 if CRC is present)
|
330 |
$substringlength = strlen($substring);
|
331 |
if ($substringlength != 9) {
|
332 |
+
$this->error('Failed to read 7 bytes at offset '.($this->ftell() - $substringlength).' (only read '.$substringlength.' bytes)');
|
333 |
return false;
|
334 |
}
|
335 |
// this would be easier with 64-bit math, but split it up to allow for 32-bit:
|
339 |
|
340 |
$info['aac']['header']['raw']['syncword'] = ($header1 & 0xFFF0) >> 4;
|
341 |
if ($info['aac']['header']['raw']['syncword'] != 0x0FFF) {
|
342 |
+
$this->error('Synch pattern (0x0FFF) not found at offset '.($this->ftell() - $substringlength).' (found 0x0'.strtoupper(dechex($info['aac']['header']['raw']['syncword'])).' instead)');
|
343 |
//if ($info['fileformat'] == 'aac') {
|
344 |
// return true;
|
345 |
//}
|
381 |
}
|
382 |
|
383 |
if ($info['aac']['header']['raw']['mpeg_layer'] != 0) {
|
384 |
+
$this->warning('Layer error - expected "0", found "'.$info['aac']['header']['raw']['mpeg_layer'].'" instead');
|
385 |
}
|
386 |
if ($info['aac']['header']['sample_frequency'] == 0) {
|
387 |
+
$this->error('Corrupt AAC file: sample_frequency == zero');
|
388 |
return false;
|
389 |
}
|
390 |
|
437 |
$info['aac']['frames'] = $framenumber;
|
438 |
$info['playtime_seconds'] = ($info['avdataend'] / $byteoffset) * (($framenumber * 1024) / $info['aac']['header']['sample_frequency']); // (1 / % of file scanned) * (samples / (samples/sec)) = seconds
|
439 |
if ($info['playtime_seconds'] == 0) {
|
440 |
+
$this->error('Corrupt AAC file: playtime_seconds == zero');
|
441 |
return false;
|
442 |
}
|
443 |
$info['audio']['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
|
452 |
// should never get here.
|
453 |
}
|
454 |
|
455 |
+
/**
|
456 |
+
* @param int $samplerateid
|
457 |
+
*
|
458 |
+
* @return int|string
|
459 |
+
*/
|
460 |
public static function AACsampleRateLookup($samplerateid) {
|
461 |
static $AACsampleRateLookup = array();
|
462 |
if (empty($AACsampleRateLookup)) {
|
480 |
return (isset($AACsampleRateLookup[$samplerateid]) ? $AACsampleRateLookup[$samplerateid] : 'invalid');
|
481 |
}
|
482 |
|
483 |
+
/**
|
484 |
+
* @param int $profileid
|
485 |
+
* @param int $mpegversion
|
486 |
+
*
|
487 |
+
* @return string
|
488 |
+
*/
|
489 |
public static function AACprofileLookup($profileid, $mpegversion) {
|
490 |
static $AACprofileLookup = array();
|
491 |
if (empty($AACprofileLookup)) {
|
501 |
return (isset($AACprofileLookup[$mpegversion][$profileid]) ? $AACprofileLookup[$mpegversion][$profileid] : 'invalid');
|
502 |
}
|
503 |
|
504 |
+
/**
|
505 |
+
* @param array $program_configs
|
506 |
+
*
|
507 |
+
* @return int
|
508 |
+
*/
|
509 |
public static function AACchannelCountCalculate($program_configs) {
|
510 |
$channels = 0;
|
511 |
for ($i = 0; $i < $program_configs['num_front_channel_elements']; $i++) {
|
lib/getid3/module.audio.ac3.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.ac3.php //
|
@@ -17,11 +17,21 @@
|
|
17 |
|
18 |
class getid3_ac3 extends getid3_handler
|
19 |
{
|
20 |
-
|
21 |
-
|
|
|
|
|
22 |
|
23 |
-
|
|
|
|
|
|
|
24 |
|
|
|
|
|
|
|
|
|
|
|
25 |
public function Analyze() {
|
26 |
$info = &$this->getid3->info;
|
27 |
|
@@ -55,185 +65,428 @@ class getid3_ac3 extends getid3_handler
|
|
55 |
// } /* end of syncinfo */
|
56 |
|
57 |
$this->fseek($info['avdataoffset']);
|
58 |
-
$
|
|
|
|
|
|
|
|
|
59 |
|
60 |
-
if (
|
61 |
-
$thisfile_ac3_raw['synchinfo']['synchword'] = self::syncword;
|
62 |
-
$offset = 2;
|
63 |
-
} else {
|
64 |
if (!$this->isDependencyFor('matroska')) {
|
65 |
unset($info['fileformat'], $info['ac3']);
|
66 |
-
return $this->error('Expecting "'.
|
67 |
}
|
68 |
-
$offset = 0;
|
69 |
-
$this->fseek(-2, SEEK_CUR);
|
70 |
}
|
71 |
|
72 |
$info['audio']['dataformat'] = 'ac3';
|
73 |
$info['audio']['bitrate_mode'] = 'cbr';
|
74 |
$info['audio']['lossless'] = false;
|
75 |
|
76 |
-
|
77 |
-
$ac3_synchinfo_fscod_frmsizecod = getid3_lib::LittleEndian2Int(substr($this->AC3header['syncinfo'], ($offset + 2), 1));
|
78 |
-
$thisfile_ac3_raw['synchinfo']['fscod'] = ($ac3_synchinfo_fscod_frmsizecod & 0xC0) >> 6;
|
79 |
-
$thisfile_ac3_raw['synchinfo']['frmsizecod'] = ($ac3_synchinfo_fscod_frmsizecod & 0x3F);
|
80 |
|
81 |
-
|
82 |
-
|
83 |
-
$
|
84 |
-
|
|
|
|
|
85 |
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
|
90 |
-
|
91 |
-
|
|
|
|
|
|
|
92 |
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
$this->error('Bit stream identification is version '.$thisfile_ac3_raw_bsi['bsid'].', but getID3() only understands up to version 8');
|
99 |
-
unset($info['ac3']);
|
100 |
-
return false;
|
101 |
-
}
|
102 |
|
103 |
-
|
104 |
-
|
|
|
|
|
|
|
105 |
|
106 |
-
|
107 |
-
$ac3_coding_mode = self::audioCodingModeLookup($thisfile_ac3_raw_bsi['acmod']);
|
108 |
-
foreach($ac3_coding_mode as $key => $value) {
|
109 |
-
$thisfile_ac3[$key] = $value;
|
110 |
-
}
|
111 |
-
switch ($thisfile_ac3_raw_bsi['acmod']) {
|
112 |
-
case 0:
|
113 |
-
case 1:
|
114 |
-
$info['audio']['channelmode'] = 'mono';
|
115 |
-
break;
|
116 |
-
case 3:
|
117 |
-
case 4:
|
118 |
-
$info['audio']['channelmode'] = 'stereo';
|
119 |
-
break;
|
120 |
-
default:
|
121 |
-
$info['audio']['channelmode'] = 'surround';
|
122 |
-
break;
|
123 |
-
}
|
124 |
-
$info['audio']['channels'] = $thisfile_ac3['num_channels'];
|
125 |
|
126 |
-
|
127 |
-
//
|
128 |
-
$thisfile_ac3_raw_bsi['
|
129 |
-
$thisfile_ac3['center_mix_level'] = self::centerMixLevelLookup($thisfile_ac3_raw_bsi['cmixlev']);
|
130 |
-
}
|
131 |
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
}
|
143 |
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
$info['audio']['channels'] .= '.1';
|
149 |
-
}
|
150 |
|
151 |
-
|
|
|
|
|
152 |
|
153 |
-
// This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31.
|
154 |
-
// The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
|
155 |
-
$thisfile_ac3_raw_bsi['dialnorm'] = $this->readHeaderBSI(5);
|
156 |
-
$thisfile_ac3['dialogue_normalization'] = '-'.$thisfile_ac3_raw_bsi['dialnorm'].'dB';
|
157 |
|
158 |
-
|
159 |
-
|
160 |
-
$thisfile_ac3_raw_bsi['compr'] = $this->readHeaderBSI(8);
|
161 |
-
$thisfile_ac3['heavy_compression'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr']);
|
162 |
-
}
|
163 |
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
|
|
168 |
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
|
174 |
-
$
|
175 |
-
$
|
176 |
-
|
|
|
|
|
|
|
|
|
|
|
177 |
|
178 |
-
|
179 |
-
// If acmod is 0, then two completely independent program channels (dual mono)
|
180 |
-
// are encoded into the bit stream, and are referenced as Ch1, Ch2. In this case,
|
181 |
-
// a number of additional items are present in BSI or audblk to fully describe Ch2.
|
182 |
|
183 |
-
|
184 |
-
// The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
|
185 |
-
$thisfile_ac3_raw_bsi['dialnorm2'] = $this->readHeaderBSI(5);
|
186 |
-
$thisfile_ac3['dialogue_normalization2'] = '-'.$thisfile_ac3_raw_bsi['dialnorm2'].'dB';
|
187 |
|
188 |
-
$thisfile_ac3_raw_bsi['
|
189 |
-
if ($thisfile_ac3_raw_bsi['
|
190 |
-
$thisfile_ac3_raw_bsi['
|
191 |
-
$thisfile_ac3['
|
|
|
|
|
|
|
192 |
}
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
$thisfile_ac3_raw_bsi['
|
|
|
|
|
197 |
}
|
198 |
|
199 |
-
$thisfile_ac3_raw_bsi['
|
200 |
-
if ($thisfile_ac3_raw_bsi['
|
201 |
-
$thisfile_ac3_raw_bsi['
|
202 |
-
$thisfile_ac3_raw_bsi['roomtyp2'] = $this->readHeaderBSI(2);
|
203 |
|
204 |
-
$
|
205 |
-
|
|
|
|
|
206 |
}
|
207 |
|
208 |
-
}
|
209 |
|
210 |
-
$thisfile_ac3_raw_bsi['
|
211 |
|
212 |
-
$thisfile_ac3_raw_bsi['original'] = (bool) $this->readHeaderBSI(1);
|
213 |
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
218 |
|
219 |
-
$thisfile_ac3_raw_bsi['timecode2_flag'] = (bool) $this->readHeaderBSI(1);
|
220 |
-
if ($thisfile_ac3_raw_bsi['timecode2_flag']) {
|
221 |
-
$thisfile_ac3_raw_bsi['timecode2'] = $this->readHeaderBSI(14);
|
222 |
}
|
223 |
|
224 |
-
$thisfile_ac3_raw_bsi['
|
225 |
-
|
226 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
227 |
|
228 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
229 |
|
230 |
-
|
231 |
-
|
|
|
232 |
}
|
233 |
|
|
|
|
|
|
|
234 |
return true;
|
235 |
}
|
236 |
|
|
|
|
|
|
|
|
|
|
|
237 |
private function readHeaderBSI($length) {
|
238 |
$data = substr($this->AC3header['bsi'], $this->BSIoffset, $length);
|
239 |
$this->BSIoffset += $length;
|
@@ -241,6 +494,11 @@ class getid3_ac3 extends getid3_handler
|
|
241 |
return bindec($data);
|
242 |
}
|
243 |
|
|
|
|
|
|
|
|
|
|
|
244 |
public static function sampleRateCodeLookup($fscod) {
|
245 |
static $sampleRateCodeLookup = array(
|
246 |
0 => 48000,
|
@@ -251,6 +509,27 @@ class getid3_ac3 extends getid3_handler
|
|
251 |
return (isset($sampleRateCodeLookup[$fscod]) ? $sampleRateCodeLookup[$fscod] : false);
|
252 |
}
|
253 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
254 |
public static function serviceTypeLookup($bsmod, $acmod) {
|
255 |
static $serviceTypeLookup = array();
|
256 |
if (empty($serviceTypeLookup)) {
|
@@ -272,6 +551,11 @@ class getid3_ac3 extends getid3_handler
|
|
272 |
return (isset($serviceTypeLookup[$bsmod][$acmod]) ? $serviceTypeLookup[$bsmod][$acmod] : false);
|
273 |
}
|
274 |
|
|
|
|
|
|
|
|
|
|
|
275 |
public static function audioCodingModeLookup($acmod) {
|
276 |
// array(channel configuration, # channels (not incl LFE), channel order)
|
277 |
static $audioCodingModeLookup = array (
|
@@ -287,6 +571,11 @@ class getid3_ac3 extends getid3_handler
|
|
287 |
return (isset($audioCodingModeLookup[$acmod]) ? $audioCodingModeLookup[$acmod] : false);
|
288 |
}
|
289 |
|
|
|
|
|
|
|
|
|
|
|
290 |
public static function centerMixLevelLookup($cmixlev) {
|
291 |
static $centerMixLevelLookup;
|
292 |
if (empty($centerMixLevelLookup)) {
|
@@ -300,6 +589,11 @@ class getid3_ac3 extends getid3_handler
|
|
300 |
return (isset($centerMixLevelLookup[$cmixlev]) ? $centerMixLevelLookup[$cmixlev] : false);
|
301 |
}
|
302 |
|
|
|
|
|
|
|
|
|
|
|
303 |
public static function surroundMixLevelLookup($surmixlev) {
|
304 |
static $surroundMixLevelLookup;
|
305 |
if (empty($surroundMixLevelLookup)) {
|
@@ -313,6 +607,11 @@ class getid3_ac3 extends getid3_handler
|
|
313 |
return (isset($surroundMixLevelLookup[$surmixlev]) ? $surroundMixLevelLookup[$surmixlev] : false);
|
314 |
}
|
315 |
|
|
|
|
|
|
|
|
|
|
|
316 |
public static function dolbySurroundModeLookup($dsurmod) {
|
317 |
static $dolbySurroundModeLookup = array(
|
318 |
0 => 'not indicated',
|
@@ -323,12 +622,18 @@ class getid3_ac3 extends getid3_handler
|
|
323 |
return (isset($dolbySurroundModeLookup[$dsurmod]) ? $dolbySurroundModeLookup[$dsurmod] : false);
|
324 |
}
|
325 |
|
|
|
|
|
|
|
|
|
|
|
|
|
326 |
public static function channelsEnabledLookup($acmod, $lfeon) {
|
327 |
$lookup = array(
|
328 |
-
'ch1'=>(
|
329 |
-
'ch2'=>(
|
330 |
-
'left'=>(
|
331 |
-
'right'=>(
|
332 |
'center'=>(bool) ($acmod & 0x01),
|
333 |
'surround_mono'=>false,
|
334 |
'surround_left'=>false,
|
@@ -348,6 +653,11 @@ class getid3_ac3 extends getid3_handler
|
|
348 |
return $lookup;
|
349 |
}
|
350 |
|
|
|
|
|
|
|
|
|
|
|
351 |
public static function heavyCompression($compre) {
|
352 |
// The first four bits indicate gain changes in 6.02dB increments which can be
|
353 |
// implemented with an arithmetic shift operation. The following four bits
|
@@ -398,6 +708,11 @@ class getid3_ac3 extends getid3_handler
|
|
398 |
return $log_gain - $lin_gain;
|
399 |
}
|
400 |
|
|
|
|
|
|
|
|
|
|
|
401 |
public static function roomTypeLookup($roomtyp) {
|
402 |
static $roomTypeLookup = array(
|
403 |
0 => 'not indicated',
|
@@ -408,32 +723,39 @@ class getid3_ac3 extends getid3_handler
|
|
408 |
return (isset($roomTypeLookup[$roomtyp]) ? $roomTypeLookup[$roomtyp] : false);
|
409 |
}
|
410 |
|
|
|
|
|
|
|
|
|
|
|
|
|
411 |
public static function frameSizeLookup($frmsizecod, $fscod) {
|
412 |
-
|
413 |
-
$
|
|
|
414 |
|
415 |
static $frameSizeLookup = array();
|
416 |
if (empty($frameSizeLookup)) {
|
417 |
$frameSizeLookup = array (
|
418 |
-
0 => array(128,
|
419 |
-
1 => array(
|
420 |
-
2 => array(
|
421 |
-
3 => array(
|
422 |
-
4 => array(
|
423 |
-
5 => array(
|
424 |
-
6 => array(
|
425 |
-
7 => array(
|
426 |
-
8 => array(
|
427 |
-
9 => array(
|
428 |
-
10 => array(
|
429 |
-
11 => array(
|
430 |
-
12 => array(
|
431 |
-
13 => array(
|
432 |
-
14 => array(
|
433 |
-
15 => array(
|
434 |
-
16 => array(
|
435 |
-
17 => array(
|
436 |
-
18 => array(
|
437 |
);
|
438 |
}
|
439 |
if (($fscod == 1) && $padding) {
|
@@ -443,20 +765,27 @@ class getid3_ac3 extends getid3_handler
|
|
443 |
return (isset($frameSizeLookup[$framesizeid][$fscod]) ? $frameSizeLookup[$framesizeid][$fscod] : false);
|
444 |
}
|
445 |
|
|
|
|
|
|
|
|
|
|
|
446 |
public static function bitrateLookup($frmsizecod) {
|
447 |
-
|
|
|
|
|
448 |
|
449 |
static $bitrateLookup = array(
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
10 => 192000,
|
461 |
11 => 224000,
|
462 |
12 => 256000,
|
@@ -465,10 +794,25 @@ class getid3_ac3 extends getid3_handler
|
|
465 |
15 => 448000,
|
466 |
16 => 512000,
|
467 |
17 => 576000,
|
468 |
-
18 => 640000
|
469 |
);
|
470 |
return (isset($bitrateLookup[$framesizeid]) ? $bitrateLookup[$framesizeid] : false);
|
471 |
}
|
472 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
473 |
|
474 |
}
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.ac3.php //
|
17 |
|
18 |
class getid3_ac3 extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @var array
|
22 |
+
*/
|
23 |
+
private $AC3header = array();
|
24 |
|
25 |
+
/**
|
26 |
+
* @var int
|
27 |
+
*/
|
28 |
+
private $BSIoffset = 0;
|
29 |
|
30 |
+
const syncword = 0x0B77;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* @return bool
|
34 |
+
*/
|
35 |
public function Analyze() {
|
36 |
$info = &$this->getid3->info;
|
37 |
|
65 |
// } /* end of syncinfo */
|
66 |
|
67 |
$this->fseek($info['avdataoffset']);
|
68 |
+
$tempAC3header = $this->fread(100); // should be enough to cover all data, there are some variable-length fields...?
|
69 |
+
$this->AC3header['syncinfo'] = getid3_lib::BigEndian2Int(substr($tempAC3header, 0, 2));
|
70 |
+
$this->AC3header['bsi'] = getid3_lib::BigEndian2Bin(substr($tempAC3header, 2));
|
71 |
+
$thisfile_ac3_raw_bsi['bsid'] = (getid3_lib::LittleEndian2Int(substr($tempAC3header, 5, 1)) & 0xF8) >> 3; // AC3 and E-AC3 put the "bsid" version identifier in the same place, but unfortnately the 4 bytes between the syncword and the version identifier are interpreted differently, so grab it here so the following code structure can make sense
|
72 |
+
unset($tempAC3header);
|
73 |
|
74 |
+
if ($this->AC3header['syncinfo'] !== self::syncword) {
|
|
|
|
|
|
|
75 |
if (!$this->isDependencyFor('matroska')) {
|
76 |
unset($info['fileformat'], $info['ac3']);
|
77 |
+
return $this->error('Expecting "'.dechex(self::syncword).'" at offset '.$info['avdataoffset'].', found "'.dechex($this->AC3header['syncinfo']).'"');
|
78 |
}
|
|
|
|
|
79 |
}
|
80 |
|
81 |
$info['audio']['dataformat'] = 'ac3';
|
82 |
$info['audio']['bitrate_mode'] = 'cbr';
|
83 |
$info['audio']['lossless'] = false;
|
84 |
|
85 |
+
if ($thisfile_ac3_raw_bsi['bsid'] <= 8) {
|
|
|
|
|
|
|
86 |
|
87 |
+
$thisfile_ac3_raw_bsi['crc1'] = getid3_lib::Bin2Dec($this->readHeaderBSI(16));
|
88 |
+
$thisfile_ac3_raw_bsi['fscod'] = $this->readHeaderBSI(2); // 5.4.1.3
|
89 |
+
$thisfile_ac3_raw_bsi['frmsizecod'] = $this->readHeaderBSI(6); // 5.4.1.4
|
90 |
+
if ($thisfile_ac3_raw_bsi['frmsizecod'] > 37) { // binary: 100101 - see Table 5.18 Frame Size Code Table (1 word = 16 bits)
|
91 |
+
$this->warning('Unexpected ac3.bsi.frmsizecod value: '.$thisfile_ac3_raw_bsi['frmsizecod'].', bitrate not set correctly');
|
92 |
+
}
|
93 |
|
94 |
+
$thisfile_ac3_raw_bsi['bsid'] = $this->readHeaderBSI(5); // we already know this from pre-parsing the version identifier, but re-read it to let the bitstream flow as intended
|
95 |
+
$thisfile_ac3_raw_bsi['bsmod'] = $this->readHeaderBSI(3);
|
96 |
+
$thisfile_ac3_raw_bsi['acmod'] = $this->readHeaderBSI(3);
|
97 |
|
98 |
+
if ($thisfile_ac3_raw_bsi['acmod'] & 0x01) {
|
99 |
+
// If the lsb of acmod is a 1, center channel is in use and cmixlev follows in the bit stream.
|
100 |
+
$thisfile_ac3_raw_bsi['cmixlev'] = $this->readHeaderBSI(2);
|
101 |
+
$thisfile_ac3['center_mix_level'] = self::centerMixLevelLookup($thisfile_ac3_raw_bsi['cmixlev']);
|
102 |
+
}
|
103 |
|
104 |
+
if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) {
|
105 |
+
// If the msb of acmod is a 1, surround channels are in use and surmixlev follows in the bit stream.
|
106 |
+
$thisfile_ac3_raw_bsi['surmixlev'] = $this->readHeaderBSI(2);
|
107 |
+
$thisfile_ac3['surround_mix_level'] = self::surroundMixLevelLookup($thisfile_ac3_raw_bsi['surmixlev']);
|
108 |
+
}
|
|
|
|
|
|
|
|
|
109 |
|
110 |
+
if ($thisfile_ac3_raw_bsi['acmod'] == 0x02) {
|
111 |
+
// When operating in the two channel mode, this 2-bit code indicates whether or not the program has been encoded in Dolby Surround.
|
112 |
+
$thisfile_ac3_raw_bsi['dsurmod'] = $this->readHeaderBSI(2);
|
113 |
+
$thisfile_ac3['dolby_surround_mode'] = self::dolbySurroundModeLookup($thisfile_ac3_raw_bsi['dsurmod']);
|
114 |
+
}
|
115 |
|
116 |
+
$thisfile_ac3_raw_bsi['flags']['lfeon'] = (bool) $this->readHeaderBSI(1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
117 |
|
118 |
+
// This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31.
|
119 |
+
// The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
|
120 |
+
$thisfile_ac3_raw_bsi['dialnorm'] = $this->readHeaderBSI(5); // 5.4.2.8 dialnorm: Dialogue Normalization, 5 Bits
|
|
|
|
|
121 |
|
122 |
+
$thisfile_ac3_raw_bsi['flags']['compr'] = (bool) $this->readHeaderBSI(1); // 5.4.2.9 compre: Compression Gain Word Exists, 1 Bit
|
123 |
+
if ($thisfile_ac3_raw_bsi['flags']['compr']) {
|
124 |
+
$thisfile_ac3_raw_bsi['compr'] = $this->readHeaderBSI(8); // 5.4.2.10 compr: Compression Gain Word, 8 Bits
|
125 |
+
$thisfile_ac3['heavy_compression'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr']);
|
126 |
+
}
|
127 |
|
128 |
+
$thisfile_ac3_raw_bsi['flags']['langcod'] = (bool) $this->readHeaderBSI(1); // 5.4.2.11 langcode: Language Code Exists, 1 Bit
|
129 |
+
if ($thisfile_ac3_raw_bsi['flags']['langcod']) {
|
130 |
+
$thisfile_ac3_raw_bsi['langcod'] = $this->readHeaderBSI(8); // 5.4.2.12 langcod: Language Code, 8 Bits
|
131 |
+
}
|
|
|
132 |
|
133 |
+
$thisfile_ac3_raw_bsi['flags']['audprodinfo'] = (bool) $this->readHeaderBSI(1); // 5.4.2.13 audprodie: Audio Production Information Exists, 1 Bit
|
134 |
+
if ($thisfile_ac3_raw_bsi['flags']['audprodinfo']) {
|
135 |
+
$thisfile_ac3_raw_bsi['mixlevel'] = $this->readHeaderBSI(5); // 5.4.2.14 mixlevel: Mixing Level, 5 Bits
|
136 |
+
$thisfile_ac3_raw_bsi['roomtyp'] = $this->readHeaderBSI(2); // 5.4.2.15 roomtyp: Room Type, 2 Bits
|
|
|
|
|
137 |
|
138 |
+
$thisfile_ac3['mixing_level'] = (80 + $thisfile_ac3_raw_bsi['mixlevel']).'dB';
|
139 |
+
$thisfile_ac3['room_type'] = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp']);
|
140 |
+
}
|
141 |
|
|
|
|
|
|
|
|
|
142 |
|
143 |
+
$thisfile_ac3_raw_bsi['dialnorm2'] = $this->readHeaderBSI(5); // 5.4.2.16 dialnorm2: Dialogue Normalization, ch2, 5 Bits
|
144 |
+
$thisfile_ac3['dialogue_normalization2'] = '-'.$thisfile_ac3_raw_bsi['dialnorm2'].'dB'; // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31. The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
|
|
|
|
|
|
|
145 |
|
146 |
+
$thisfile_ac3_raw_bsi['flags']['compr2'] = (bool) $this->readHeaderBSI(1); // 5.4.2.17 compr2e: Compression Gain Word Exists, ch2, 1 Bit
|
147 |
+
if ($thisfile_ac3_raw_bsi['flags']['compr2']) {
|
148 |
+
$thisfile_ac3_raw_bsi['compr2'] = $this->readHeaderBSI(8); // 5.4.2.18 compr2: Compression Gain Word, ch2, 8 Bits
|
149 |
+
$thisfile_ac3['heavy_compression2'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr2']);
|
150 |
+
}
|
151 |
|
152 |
+
$thisfile_ac3_raw_bsi['flags']['langcod2'] = (bool) $this->readHeaderBSI(1); // 5.4.2.19 langcod2e: Language Code Exists, ch2, 1 Bit
|
153 |
+
if ($thisfile_ac3_raw_bsi['flags']['langcod2']) {
|
154 |
+
$thisfile_ac3_raw_bsi['langcod2'] = $this->readHeaderBSI(8); // 5.4.2.20 langcod2: Language Code, ch2, 8 Bits
|
155 |
+
}
|
156 |
|
157 |
+
$thisfile_ac3_raw_bsi['flags']['audprodinfo2'] = (bool) $this->readHeaderBSI(1); // 5.4.2.21 audprodi2e: Audio Production Information Exists, ch2, 1 Bit
|
158 |
+
if ($thisfile_ac3_raw_bsi['flags']['audprodinfo2']) {
|
159 |
+
$thisfile_ac3_raw_bsi['mixlevel2'] = $this->readHeaderBSI(5); // 5.4.2.22 mixlevel2: Mixing Level, ch2, 5 Bits
|
160 |
+
$thisfile_ac3_raw_bsi['roomtyp2'] = $this->readHeaderBSI(2); // 5.4.2.23 roomtyp2: Room Type, ch2, 2 Bits
|
161 |
+
|
162 |
+
$thisfile_ac3['mixing_level2'] = (80 + $thisfile_ac3_raw_bsi['mixlevel2']).'dB';
|
163 |
+
$thisfile_ac3['room_type2'] = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp2']);
|
164 |
+
}
|
165 |
|
166 |
+
$thisfile_ac3_raw_bsi['copyright'] = (bool) $this->readHeaderBSI(1); // 5.4.2.24 copyrightb: Copyright Bit, 1 Bit
|
|
|
|
|
|
|
167 |
|
168 |
+
$thisfile_ac3_raw_bsi['original'] = (bool) $this->readHeaderBSI(1); // 5.4.2.25 origbs: Original Bit Stream, 1 Bit
|
|
|
|
|
|
|
169 |
|
170 |
+
$thisfile_ac3_raw_bsi['flags']['timecod1'] = $this->readHeaderBSI(2); // 5.4.2.26 timecod1e, timcode2e: Time Code (first and second) Halves Exist, 2 Bits
|
171 |
+
if ($thisfile_ac3_raw_bsi['flags']['timecod1'] & 0x01) {
|
172 |
+
$thisfile_ac3_raw_bsi['timecod1'] = $this->readHeaderBSI(14); // 5.4.2.27 timecod1: Time code first half, 14 bits
|
173 |
+
$thisfile_ac3['timecode1'] = 0;
|
174 |
+
$thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x3E00) >> 9) * 3600; // The first 5 bits of this 14-bit field represent the time in hours, with valid values of 0�23
|
175 |
+
$thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x01F8) >> 3) * 60; // The next 6 bits represent the time in minutes, with valid values of 0�59
|
176 |
+
$thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x0003) >> 0) * 8; // The final 3 bits represents the time in 8 second increments, with valid values of 0�7 (representing 0, 8, 16, ... 56 seconds)
|
177 |
}
|
178 |
+
if ($thisfile_ac3_raw_bsi['flags']['timecod1'] & 0x02) {
|
179 |
+
$thisfile_ac3_raw_bsi['timecod2'] = $this->readHeaderBSI(14); // 5.4.2.28 timecod2: Time code second half, 14 bits
|
180 |
+
$thisfile_ac3['timecode2'] = 0;
|
181 |
+
$thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x3800) >> 11) * 1; // The first 3 bits of this 14-bit field represent the time in seconds, with valid values from 0�7 (representing 0-7 seconds)
|
182 |
+
$thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x07C0) >> 6) * (1 / 30); // The next 5 bits represents the time in frames, with valid values from 0�29 (one frame = 1/30th of a second)
|
183 |
+
$thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x003F) >> 0) * ((1 / 30) / 60); // The final 6 bits represents fractions of 1/64 of a frame, with valid values from 0�63
|
184 |
}
|
185 |
|
186 |
+
$thisfile_ac3_raw_bsi['flags']['addbsi'] = (bool) $this->readHeaderBSI(1);
|
187 |
+
if ($thisfile_ac3_raw_bsi['flags']['addbsi']) {
|
188 |
+
$thisfile_ac3_raw_bsi['addbsi_length'] = $this->readHeaderBSI(6) + 1; // This 6-bit code, which exists only if addbside is a 1, indicates the length in bytes of additional bit stream information. The valid range of addbsil is 0�63, indicating 1�64 additional bytes, respectively.
|
|
|
189 |
|
190 |
+
$this->AC3header['bsi'] .= getid3_lib::BigEndian2Bin($this->fread($thisfile_ac3_raw_bsi['addbsi_length']));
|
191 |
+
|
192 |
+
$thisfile_ac3_raw_bsi['addbsi_data'] = substr($this->AC3header['bsi'], $this->BSIoffset, $thisfile_ac3_raw_bsi['addbsi_length'] * 8);
|
193 |
+
$this->BSIoffset += $thisfile_ac3_raw_bsi['addbsi_length'] * 8;
|
194 |
}
|
195 |
|
|
|
196 |
|
197 |
+
} elseif ($thisfile_ac3_raw_bsi['bsid'] <= 16) { // E-AC3
|
198 |
|
|
|
199 |
|
200 |
+
$this->error('E-AC3 parsing is incomplete and experimental in this version of getID3 ('.$this->getid3->version().'). Notably the bitrate calculations are wrong -- value might (or not) be correct, but it is not calculated correctly. Email info@getid3.org if you know how to calculate EAC3 bitrate correctly.');
|
201 |
+
$info['audio']['dataformat'] = 'eac3';
|
202 |
+
|
203 |
+
$thisfile_ac3_raw_bsi['strmtyp'] = $this->readHeaderBSI(2);
|
204 |
+
$thisfile_ac3_raw_bsi['substreamid'] = $this->readHeaderBSI(3);
|
205 |
+
$thisfile_ac3_raw_bsi['frmsiz'] = $this->readHeaderBSI(11);
|
206 |
+
$thisfile_ac3_raw_bsi['fscod'] = $this->readHeaderBSI(2);
|
207 |
+
if ($thisfile_ac3_raw_bsi['fscod'] == 3) {
|
208 |
+
$thisfile_ac3_raw_bsi['fscod2'] = $this->readHeaderBSI(2);
|
209 |
+
$thisfile_ac3_raw_bsi['numblkscod'] = 3; // six blocks per syncframe
|
210 |
+
} else {
|
211 |
+
$thisfile_ac3_raw_bsi['numblkscod'] = $this->readHeaderBSI(2);
|
212 |
+
}
|
213 |
+
$thisfile_ac3['bsi']['blocks_per_sync_frame'] = self::blocksPerSyncFrame($thisfile_ac3_raw_bsi['numblkscod']);
|
214 |
+
$thisfile_ac3_raw_bsi['acmod'] = $this->readHeaderBSI(3);
|
215 |
+
$thisfile_ac3_raw_bsi['flags']['lfeon'] = (bool) $this->readHeaderBSI(1);
|
216 |
+
$thisfile_ac3_raw_bsi['bsid'] = $this->readHeaderBSI(5); // we already know this from pre-parsing the version identifier, but re-read it to let the bitstream flow as intended
|
217 |
+
$thisfile_ac3_raw_bsi['dialnorm'] = $this->readHeaderBSI(5);
|
218 |
+
$thisfile_ac3_raw_bsi['flags']['compr'] = (bool) $this->readHeaderBSI(1);
|
219 |
+
if ($thisfile_ac3_raw_bsi['flags']['compr']) {
|
220 |
+
$thisfile_ac3_raw_bsi['compr'] = $this->readHeaderBSI(8);
|
221 |
+
}
|
222 |
+
if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
|
223 |
+
$thisfile_ac3_raw_bsi['dialnorm2'] = $this->readHeaderBSI(5);
|
224 |
+
$thisfile_ac3_raw_bsi['flags']['compr2'] = (bool) $this->readHeaderBSI(1);
|
225 |
+
if ($thisfile_ac3_raw_bsi['flags']['compr2']) {
|
226 |
+
$thisfile_ac3_raw_bsi['compr2'] = $this->readHeaderBSI(8);
|
227 |
+
}
|
228 |
+
}
|
229 |
+
if ($thisfile_ac3_raw_bsi['strmtyp'] == 1) { // if dependent stream
|
230 |
+
$thisfile_ac3_raw_bsi['flags']['chanmap'] = (bool) $this->readHeaderBSI(1);
|
231 |
+
if ($thisfile_ac3_raw_bsi['flags']['chanmap']) {
|
232 |
+
$thisfile_ac3_raw_bsi['chanmap'] = $this->readHeaderBSI(8);
|
233 |
+
}
|
234 |
+
}
|
235 |
+
$thisfile_ac3_raw_bsi['flags']['mixmdat'] = (bool) $this->readHeaderBSI(1);
|
236 |
+
if ($thisfile_ac3_raw_bsi['flags']['mixmdat']) { // Mixing metadata
|
237 |
+
if ($thisfile_ac3_raw_bsi['acmod'] > 2) { // if more than 2 channels
|
238 |
+
$thisfile_ac3_raw_bsi['dmixmod'] = $this->readHeaderBSI(2);
|
239 |
+
}
|
240 |
+
if (($thisfile_ac3_raw_bsi['acmod'] & 0x01) && ($thisfile_ac3_raw_bsi['acmod'] > 2)) { // if three front channels exist
|
241 |
+
$thisfile_ac3_raw_bsi['ltrtcmixlev'] = $this->readHeaderBSI(3);
|
242 |
+
$thisfile_ac3_raw_bsi['lorocmixlev'] = $this->readHeaderBSI(3);
|
243 |
+
}
|
244 |
+
if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) { // if a surround channel exists
|
245 |
+
$thisfile_ac3_raw_bsi['ltrtsurmixlev'] = $this->readHeaderBSI(3);
|
246 |
+
$thisfile_ac3_raw_bsi['lorosurmixlev'] = $this->readHeaderBSI(3);
|
247 |
+
}
|
248 |
+
if ($thisfile_ac3_raw_bsi['flags']['lfeon']) { // if the LFE channel exists
|
249 |
+
$thisfile_ac3_raw_bsi['flags']['lfemixlevcod'] = (bool) $this->readHeaderBSI(1);
|
250 |
+
if ($thisfile_ac3_raw_bsi['flags']['lfemixlevcod']) {
|
251 |
+
$thisfile_ac3_raw_bsi['lfemixlevcod'] = $this->readHeaderBSI(5);
|
252 |
+
}
|
253 |
+
}
|
254 |
+
if ($thisfile_ac3_raw_bsi['strmtyp'] == 0) { // if independent stream
|
255 |
+
$thisfile_ac3_raw_bsi['flags']['pgmscl'] = (bool) $this->readHeaderBSI(1);
|
256 |
+
if ($thisfile_ac3_raw_bsi['flags']['pgmscl']) {
|
257 |
+
$thisfile_ac3_raw_bsi['pgmscl'] = $this->readHeaderBSI(6);
|
258 |
+
}
|
259 |
+
if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
|
260 |
+
$thisfile_ac3_raw_bsi['flags']['pgmscl2'] = (bool) $this->readHeaderBSI(1);
|
261 |
+
if ($thisfile_ac3_raw_bsi['flags']['pgmscl2']) {
|
262 |
+
$thisfile_ac3_raw_bsi['pgmscl2'] = $this->readHeaderBSI(6);
|
263 |
+
}
|
264 |
+
}
|
265 |
+
$thisfile_ac3_raw_bsi['flags']['extpgmscl'] = (bool) $this->readHeaderBSI(1);
|
266 |
+
if ($thisfile_ac3_raw_bsi['flags']['extpgmscl']) {
|
267 |
+
$thisfile_ac3_raw_bsi['extpgmscl'] = $this->readHeaderBSI(6);
|
268 |
+
}
|
269 |
+
$thisfile_ac3_raw_bsi['mixdef'] = $this->readHeaderBSI(2);
|
270 |
+
if ($thisfile_ac3_raw_bsi['mixdef'] == 1) { // mixing option 2
|
271 |
+
$thisfile_ac3_raw_bsi['premixcmpsel'] = (bool) $this->readHeaderBSI(1);
|
272 |
+
$thisfile_ac3_raw_bsi['drcsrc'] = (bool) $this->readHeaderBSI(1);
|
273 |
+
$thisfile_ac3_raw_bsi['premixcmpscl'] = $this->readHeaderBSI(3);
|
274 |
+
} elseif ($thisfile_ac3_raw_bsi['mixdef'] == 2) { // mixing option 3
|
275 |
+
$thisfile_ac3_raw_bsi['mixdata'] = $this->readHeaderBSI(12);
|
276 |
+
} elseif ($thisfile_ac3_raw_bsi['mixdef'] == 3) { // mixing option 4
|
277 |
+
$mixdefbitsread = 0;
|
278 |
+
$thisfile_ac3_raw_bsi['mixdeflen'] = $this->readHeaderBSI(5); $mixdefbitsread += 5;
|
279 |
+
$thisfile_ac3_raw_bsi['flags']['mixdata2'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
|
280 |
+
if ($thisfile_ac3_raw_bsi['flags']['mixdata2']) {
|
281 |
+
$thisfile_ac3_raw_bsi['premixcmpsel'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
|
282 |
+
$thisfile_ac3_raw_bsi['drcsrc'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
|
283 |
+
$thisfile_ac3_raw_bsi['premixcmpscl'] = $this->readHeaderBSI(3); $mixdefbitsread += 3;
|
284 |
+
$thisfile_ac3_raw_bsi['flags']['extpgmlscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
|
285 |
+
if ($thisfile_ac3_raw_bsi['flags']['extpgmlscl']) {
|
286 |
+
$thisfile_ac3_raw_bsi['extpgmlscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
|
287 |
+
}
|
288 |
+
$thisfile_ac3_raw_bsi['flags']['extpgmcscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
|
289 |
+
if ($thisfile_ac3_raw_bsi['flags']['extpgmcscl']) {
|
290 |
+
$thisfile_ac3_raw_bsi['extpgmcscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
|
291 |
+
}
|
292 |
+
$thisfile_ac3_raw_bsi['flags']['extpgmrscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
|
293 |
+
if ($thisfile_ac3_raw_bsi['flags']['extpgmrscl']) {
|
294 |
+
$thisfile_ac3_raw_bsi['extpgmrscl'] = $this->readHeaderBSI(4);
|
295 |
+
}
|
296 |
+
$thisfile_ac3_raw_bsi['flags']['extpgmlsscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
|
297 |
+
if ($thisfile_ac3_raw_bsi['flags']['extpgmlsscl']) {
|
298 |
+
$thisfile_ac3_raw_bsi['extpgmlsscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
|
299 |
+
}
|
300 |
+
$thisfile_ac3_raw_bsi['flags']['extpgmrsscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
|
301 |
+
if ($thisfile_ac3_raw_bsi['flags']['extpgmrsscl']) {
|
302 |
+
$thisfile_ac3_raw_bsi['extpgmrsscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
|
303 |
+
}
|
304 |
+
$thisfile_ac3_raw_bsi['flags']['extpgmlfescl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
|
305 |
+
if ($thisfile_ac3_raw_bsi['flags']['extpgmlfescl']) {
|
306 |
+
$thisfile_ac3_raw_bsi['extpgmlfescl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
|
307 |
+
}
|
308 |
+
$thisfile_ac3_raw_bsi['flags']['dmixscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
|
309 |
+
if ($thisfile_ac3_raw_bsi['flags']['dmixscl']) {
|
310 |
+
$thisfile_ac3_raw_bsi['dmixscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
|
311 |
+
}
|
312 |
+
$thisfile_ac3_raw_bsi['flags']['addch'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
|
313 |
+
if ($thisfile_ac3_raw_bsi['flags']['addch']) {
|
314 |
+
$thisfile_ac3_raw_bsi['flags']['extpgmaux1scl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
|
315 |
+
if ($thisfile_ac3_raw_bsi['flags']['extpgmaux1scl']) {
|
316 |
+
$thisfile_ac3_raw_bsi['extpgmaux1scl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
|
317 |
+
}
|
318 |
+
$thisfile_ac3_raw_bsi['flags']['extpgmaux2scl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
|
319 |
+
if ($thisfile_ac3_raw_bsi['flags']['extpgmaux2scl']) {
|
320 |
+
$thisfile_ac3_raw_bsi['extpgmaux2scl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
|
321 |
+
}
|
322 |
+
}
|
323 |
+
}
|
324 |
+
$thisfile_ac3_raw_bsi['flags']['mixdata3'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
|
325 |
+
if ($thisfile_ac3_raw_bsi['flags']['mixdata3']) {
|
326 |
+
$thisfile_ac3_raw_bsi['spchdat'] = $this->readHeaderBSI(5); $mixdefbitsread += 5;
|
327 |
+
$thisfile_ac3_raw_bsi['flags']['addspchdat'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
|
328 |
+
if ($thisfile_ac3_raw_bsi['flags']['addspchdat']) {
|
329 |
+
$thisfile_ac3_raw_bsi['spchdat1'] = $this->readHeaderBSI(5); $mixdefbitsread += 5;
|
330 |
+
$thisfile_ac3_raw_bsi['spchan1att'] = $this->readHeaderBSI(2); $mixdefbitsread += 2;
|
331 |
+
$thisfile_ac3_raw_bsi['flags']['addspchdat1'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
|
332 |
+
if ($thisfile_ac3_raw_bsi['flags']['addspchdat1']) {
|
333 |
+
$thisfile_ac3_raw_bsi['spchdat2'] = $this->readHeaderBSI(5); $mixdefbitsread += 5;
|
334 |
+
$thisfile_ac3_raw_bsi['spchan2att'] = $this->readHeaderBSI(3); $mixdefbitsread += 3;
|
335 |
+
}
|
336 |
+
}
|
337 |
+
}
|
338 |
+
$mixdata_bits = (8 * ($thisfile_ac3_raw_bsi['mixdeflen'] + 2)) - $mixdefbitsread;
|
339 |
+
$mixdata_fill = (($mixdata_bits % 8) ? 8 - ($mixdata_bits % 8) : 0);
|
340 |
+
$thisfile_ac3_raw_bsi['mixdata'] = $this->readHeaderBSI($mixdata_bits);
|
341 |
+
$thisfile_ac3_raw_bsi['mixdatafill'] = $this->readHeaderBSI($mixdata_fill);
|
342 |
+
unset($mixdefbitsread, $mixdata_bits, $mixdata_fill);
|
343 |
+
}
|
344 |
+
if ($thisfile_ac3_raw_bsi['acmod'] < 2) { // if mono or dual mono source
|
345 |
+
$thisfile_ac3_raw_bsi['flags']['paninfo'] = (bool) $this->readHeaderBSI(1);
|
346 |
+
if ($thisfile_ac3_raw_bsi['flags']['paninfo']) {
|
347 |
+
$thisfile_ac3_raw_bsi['panmean'] = $this->readHeaderBSI(8);
|
348 |
+
$thisfile_ac3_raw_bsi['paninfo'] = $this->readHeaderBSI(6);
|
349 |
+
}
|
350 |
+
if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
|
351 |
+
$thisfile_ac3_raw_bsi['flags']['paninfo2'] = (bool) $this->readHeaderBSI(1);
|
352 |
+
if ($thisfile_ac3_raw_bsi['flags']['paninfo2']) {
|
353 |
+
$thisfile_ac3_raw_bsi['panmean2'] = $this->readHeaderBSI(8);
|
354 |
+
$thisfile_ac3_raw_bsi['paninfo2'] = $this->readHeaderBSI(6);
|
355 |
+
}
|
356 |
+
}
|
357 |
+
}
|
358 |
+
$thisfile_ac3_raw_bsi['flags']['frmmixcfginfo'] = (bool) $this->readHeaderBSI(1);
|
359 |
+
if ($thisfile_ac3_raw_bsi['flags']['frmmixcfginfo']) { // mixing configuration information
|
360 |
+
if ($thisfile_ac3_raw_bsi['numblkscod'] == 0) {
|
361 |
+
$thisfile_ac3_raw_bsi['blkmixcfginfo'][0] = $this->readHeaderBSI(5);
|
362 |
+
} else {
|
363 |
+
for ($blk = 0; $blk < $thisfile_ac3_raw_bsi['numblkscod']; $blk++) {
|
364 |
+
$thisfile_ac3_raw_bsi['flags']['blkmixcfginfo'.$blk] = (bool) $this->readHeaderBSI(1);
|
365 |
+
if ($thisfile_ac3_raw_bsi['flags']['blkmixcfginfo'.$blk]) { // mixing configuration information
|
366 |
+
$thisfile_ac3_raw_bsi['blkmixcfginfo'][$blk] = $this->readHeaderBSI(5);
|
367 |
+
}
|
368 |
+
}
|
369 |
+
}
|
370 |
+
}
|
371 |
+
}
|
372 |
+
}
|
373 |
+
$thisfile_ac3_raw_bsi['flags']['infomdat'] = (bool) $this->readHeaderBSI(1);
|
374 |
+
if ($thisfile_ac3_raw_bsi['flags']['infomdat']) { // Informational metadata
|
375 |
+
$thisfile_ac3_raw_bsi['bsmod'] = $this->readHeaderBSI(3);
|
376 |
+
$thisfile_ac3_raw_bsi['flags']['copyrightb'] = (bool) $this->readHeaderBSI(1);
|
377 |
+
$thisfile_ac3_raw_bsi['flags']['origbs'] = (bool) $this->readHeaderBSI(1);
|
378 |
+
if ($thisfile_ac3_raw_bsi['acmod'] == 2) { // if in 2/0 mode
|
379 |
+
$thisfile_ac3_raw_bsi['dsurmod'] = $this->readHeaderBSI(2);
|
380 |
+
$thisfile_ac3_raw_bsi['dheadphonmod'] = $this->readHeaderBSI(2);
|
381 |
+
}
|
382 |
+
if ($thisfile_ac3_raw_bsi['acmod'] >= 6) { // if both surround channels exist
|
383 |
+
$thisfile_ac3_raw_bsi['dsurexmod'] = $this->readHeaderBSI(2);
|
384 |
+
}
|
385 |
+
$thisfile_ac3_raw_bsi['flags']['audprodi'] = (bool) $this->readHeaderBSI(1);
|
386 |
+
if ($thisfile_ac3_raw_bsi['flags']['audprodi']) {
|
387 |
+
$thisfile_ac3_raw_bsi['mixlevel'] = $this->readHeaderBSI(5);
|
388 |
+
$thisfile_ac3_raw_bsi['roomtyp'] = $this->readHeaderBSI(2);
|
389 |
+
$thisfile_ac3_raw_bsi['flags']['adconvtyp'] = (bool) $this->readHeaderBSI(1);
|
390 |
+
}
|
391 |
+
if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
|
392 |
+
$thisfile_ac3_raw_bsi['flags']['audprodi2'] = (bool) $this->readHeaderBSI(1);
|
393 |
+
if ($thisfile_ac3_raw_bsi['flags']['audprodi2']) {
|
394 |
+
$thisfile_ac3_raw_bsi['mixlevel2'] = $this->readHeaderBSI(5);
|
395 |
+
$thisfile_ac3_raw_bsi['roomtyp2'] = $this->readHeaderBSI(2);
|
396 |
+
$thisfile_ac3_raw_bsi['flags']['adconvtyp2'] = (bool) $this->readHeaderBSI(1);
|
397 |
+
}
|
398 |
+
}
|
399 |
+
if ($thisfile_ac3_raw_bsi['fscod'] < 3) { // if not half sample rate
|
400 |
+
$thisfile_ac3_raw_bsi['flags']['sourcefscod'] = (bool) $this->readHeaderBSI(1);
|
401 |
+
}
|
402 |
+
}
|
403 |
+
if (($thisfile_ac3_raw_bsi['strmtyp'] == 0) && ($thisfile_ac3_raw_bsi['numblkscod'] != 3)) { // if both surround channels exist
|
404 |
+
$thisfile_ac3_raw_bsi['flags']['convsync'] = (bool) $this->readHeaderBSI(1);
|
405 |
+
}
|
406 |
+
if ($thisfile_ac3_raw_bsi['strmtyp'] == 2) { // if bit stream converted from AC-3
|
407 |
+
if ($thisfile_ac3_raw_bsi['numblkscod'] != 3) { // 6 blocks per syncframe
|
408 |
+
$thisfile_ac3_raw_bsi['flags']['blkid'] = 1;
|
409 |
+
} else {
|
410 |
+
$thisfile_ac3_raw_bsi['flags']['blkid'] = (bool) $this->readHeaderBSI(1);
|
411 |
+
}
|
412 |
+
if ($thisfile_ac3_raw_bsi['flags']['blkid']) {
|
413 |
+
$thisfile_ac3_raw_bsi['frmsizecod'] = $this->readHeaderBSI(6);
|
414 |
+
}
|
415 |
+
}
|
416 |
+
$thisfile_ac3_raw_bsi['flags']['addbsi'] = (bool) $this->readHeaderBSI(1);
|
417 |
+
if ($thisfile_ac3_raw_bsi['flags']['addbsi']) {
|
418 |
+
$thisfile_ac3_raw_bsi['addbsil'] = $this->readHeaderBSI(6);
|
419 |
+
$thisfile_ac3_raw_bsi['addbsi'] = $this->readHeaderBSI(($thisfile_ac3_raw_bsi['addbsil'] + 1) * 8);
|
420 |
+
}
|
421 |
+
|
422 |
+
} else {
|
423 |
+
|
424 |
+
$this->error('Bit stream identification is version '.$thisfile_ac3_raw_bsi['bsid'].', but getID3() only understands up to version 16. Please submit a support ticket with a sample file.');
|
425 |
+
unset($info['ac3']);
|
426 |
+
return false;
|
427 |
|
|
|
|
|
|
|
428 |
}
|
429 |
|
430 |
+
if (isset($thisfile_ac3_raw_bsi['fscod2'])) {
|
431 |
+
$thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup2($thisfile_ac3_raw_bsi['fscod2']);
|
432 |
+
} else {
|
433 |
+
$thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup($thisfile_ac3_raw_bsi['fscod']);
|
434 |
+
}
|
435 |
+
if ($thisfile_ac3_raw_bsi['fscod'] <= 3) {
|
436 |
+
$info['audio']['sample_rate'] = $thisfile_ac3['sample_rate'];
|
437 |
+
} else {
|
438 |
+
$this->warning('Unexpected ac3.bsi.fscod value: '.$thisfile_ac3_raw_bsi['fscod']);
|
439 |
+
}
|
440 |
+
if (isset($thisfile_ac3_raw_bsi['frmsizecod'])) {
|
441 |
+
$thisfile_ac3['frame_length'] = self::frameSizeLookup($thisfile_ac3_raw_bsi['frmsizecod'], $thisfile_ac3_raw_bsi['fscod']);
|
442 |
+
$thisfile_ac3['bitrate'] = self::bitrateLookup($thisfile_ac3_raw_bsi['frmsizecod']);
|
443 |
+
} elseif (!empty($thisfile_ac3_raw_bsi['frmsiz'])) {
|
444 |
+
// this isn't right, but it's (usually) close, roughly 5% less than it should be.
|
445 |
+
// but WHERE is the actual bitrate value stored in EAC3?? email info@getid3.org if you know!
|
446 |
+
$thisfile_ac3['bitrate'] = ($thisfile_ac3_raw_bsi['frmsiz'] + 1) * 16 * 30; // The frmsiz field shall contain a value one less than the overall size of the coded syncframe in 16-bit words. That is, this field may assume a value ranging from 0 to 2047, and these values correspond to syncframe sizes ranging from 1 to 2048.
|
447 |
+
// kludge-fix to make it approximately the expected value, still not "right":
|
448 |
+
$thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16000;
|
449 |
+
}
|
450 |
+
$info['audio']['bitrate'] = $thisfile_ac3['bitrate'];
|
451 |
|
452 |
+
if (isset($thisfile_ac3_raw_bsi['bsmod']) && isset($thisfile_ac3_raw_bsi['acmod'])) {
|
453 |
+
$thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']);
|
454 |
+
}
|
455 |
+
$ac3_coding_mode = self::audioCodingModeLookup($thisfile_ac3_raw_bsi['acmod']);
|
456 |
+
foreach($ac3_coding_mode as $key => $value) {
|
457 |
+
$thisfile_ac3[$key] = $value;
|
458 |
+
}
|
459 |
+
switch ($thisfile_ac3_raw_bsi['acmod']) {
|
460 |
+
case 0:
|
461 |
+
case 1:
|
462 |
+
$info['audio']['channelmode'] = 'mono';
|
463 |
+
break;
|
464 |
+
case 3:
|
465 |
+
case 4:
|
466 |
+
$info['audio']['channelmode'] = 'stereo';
|
467 |
+
break;
|
468 |
+
default:
|
469 |
+
$info['audio']['channelmode'] = 'surround';
|
470 |
+
break;
|
471 |
+
}
|
472 |
+
$info['audio']['channels'] = $thisfile_ac3['num_channels'];
|
473 |
|
474 |
+
$thisfile_ac3['lfe_enabled'] = $thisfile_ac3_raw_bsi['flags']['lfeon'];
|
475 |
+
if ($thisfile_ac3_raw_bsi['flags']['lfeon']) {
|
476 |
+
$info['audio']['channels'] .= '.1';
|
477 |
}
|
478 |
|
479 |
+
$thisfile_ac3['channels_enabled'] = self::channelsEnabledLookup($thisfile_ac3_raw_bsi['acmod'], $thisfile_ac3_raw_bsi['flags']['lfeon']);
|
480 |
+
$thisfile_ac3['dialogue_normalization'] = '-'.$thisfile_ac3_raw_bsi['dialnorm'].'dB';
|
481 |
+
|
482 |
return true;
|
483 |
}
|
484 |
|
485 |
+
/**
|
486 |
+
* @param int $length
|
487 |
+
*
|
488 |
+
* @return float|int
|
489 |
+
*/
|
490 |
private function readHeaderBSI($length) {
|
491 |
$data = substr($this->AC3header['bsi'], $this->BSIoffset, $length);
|
492 |
$this->BSIoffset += $length;
|
494 |
return bindec($data);
|
495 |
}
|
496 |
|
497 |
+
/**
|
498 |
+
* @param int $fscod
|
499 |
+
*
|
500 |
+
* @return int|string|false
|
501 |
+
*/
|
502 |
public static function sampleRateCodeLookup($fscod) {
|
503 |
static $sampleRateCodeLookup = array(
|
504 |
0 => 48000,
|
509 |
return (isset($sampleRateCodeLookup[$fscod]) ? $sampleRateCodeLookup[$fscod] : false);
|
510 |
}
|
511 |
|
512 |
+
/**
|
513 |
+
* @param int $fscod2
|
514 |
+
*
|
515 |
+
* @return int|string|false
|
516 |
+
*/
|
517 |
+
public static function sampleRateCodeLookup2($fscod2) {
|
518 |
+
static $sampleRateCodeLookup2 = array(
|
519 |
+
0 => 24000,
|
520 |
+
1 => 22050,
|
521 |
+
2 => 16000,
|
522 |
+
3 => 'reserved' // If the reserved code is indicated, the decoder should not attempt to decode audio and should mute.
|
523 |
+
);
|
524 |
+
return (isset($sampleRateCodeLookup2[$fscod2]) ? $sampleRateCodeLookup2[$fscod2] : false);
|
525 |
+
}
|
526 |
+
|
527 |
+
/**
|
528 |
+
* @param int $bsmod
|
529 |
+
* @param int $acmod
|
530 |
+
*
|
531 |
+
* @return string|false
|
532 |
+
*/
|
533 |
public static function serviceTypeLookup($bsmod, $acmod) {
|
534 |
static $serviceTypeLookup = array();
|
535 |
if (empty($serviceTypeLookup)) {
|
551 |
return (isset($serviceTypeLookup[$bsmod][$acmod]) ? $serviceTypeLookup[$bsmod][$acmod] : false);
|
552 |
}
|
553 |
|
554 |
+
/**
|
555 |
+
* @param int $acmod
|
556 |
+
*
|
557 |
+
* @return array|false
|
558 |
+
*/
|
559 |
public static function audioCodingModeLookup($acmod) {
|
560 |
// array(channel configuration, # channels (not incl LFE), channel order)
|
561 |
static $audioCodingModeLookup = array (
|
571 |
return (isset($audioCodingModeLookup[$acmod]) ? $audioCodingModeLookup[$acmod] : false);
|
572 |
}
|
573 |
|
574 |
+
/**
|
575 |
+
* @param int $cmixlev
|
576 |
+
*
|
577 |
+
* @return int|float|string|false
|
578 |
+
*/
|
579 |
public static function centerMixLevelLookup($cmixlev) {
|
580 |
static $centerMixLevelLookup;
|
581 |
if (empty($centerMixLevelLookup)) {
|
589 |
return (isset($centerMixLevelLookup[$cmixlev]) ? $centerMixLevelLookup[$cmixlev] : false);
|
590 |
}
|
591 |
|
592 |
+
/**
|
593 |
+
* @param int $surmixlev
|
594 |
+
*
|
595 |
+
* @return int|float|string|false
|
596 |
+
*/
|
597 |
public static function surroundMixLevelLookup($surmixlev) {
|
598 |
static $surroundMixLevelLookup;
|
599 |
if (empty($surroundMixLevelLookup)) {
|
607 |
return (isset($surroundMixLevelLookup[$surmixlev]) ? $surroundMixLevelLookup[$surmixlev] : false);
|
608 |
}
|
609 |
|
610 |
+
/**
|
611 |
+
* @param int $dsurmod
|
612 |
+
*
|
613 |
+
* @return string|false
|
614 |
+
*/
|
615 |
public static function dolbySurroundModeLookup($dsurmod) {
|
616 |
static $dolbySurroundModeLookup = array(
|
617 |
0 => 'not indicated',
|
622 |
return (isset($dolbySurroundModeLookup[$dsurmod]) ? $dolbySurroundModeLookup[$dsurmod] : false);
|
623 |
}
|
624 |
|
625 |
+
/**
|
626 |
+
* @param int $acmod
|
627 |
+
* @param bool $lfeon
|
628 |
+
*
|
629 |
+
* @return array
|
630 |
+
*/
|
631 |
public static function channelsEnabledLookup($acmod, $lfeon) {
|
632 |
$lookup = array(
|
633 |
+
'ch1'=>($acmod == 0),
|
634 |
+
'ch2'=>($acmod == 0),
|
635 |
+
'left'=>($acmod > 1),
|
636 |
+
'right'=>($acmod > 1),
|
637 |
'center'=>(bool) ($acmod & 0x01),
|
638 |
'surround_mono'=>false,
|
639 |
'surround_left'=>false,
|
653 |
return $lookup;
|
654 |
}
|
655 |
|
656 |
+
/**
|
657 |
+
* @param int $compre
|
658 |
+
*
|
659 |
+
* @return float|int
|
660 |
+
*/
|
661 |
public static function heavyCompression($compre) {
|
662 |
// The first four bits indicate gain changes in 6.02dB increments which can be
|
663 |
// implemented with an arithmetic shift operation. The following four bits
|
708 |
return $log_gain - $lin_gain;
|
709 |
}
|
710 |
|
711 |
+
/**
|
712 |
+
* @param int $roomtyp
|
713 |
+
*
|
714 |
+
* @return string|false
|
715 |
+
*/
|
716 |
public static function roomTypeLookup($roomtyp) {
|
717 |
static $roomTypeLookup = array(
|
718 |
0 => 'not indicated',
|
723 |
return (isset($roomTypeLookup[$roomtyp]) ? $roomTypeLookup[$roomtyp] : false);
|
724 |
}
|
725 |
|
726 |
+
/**
|
727 |
+
* @param int $frmsizecod
|
728 |
+
* @param int $fscod
|
729 |
+
*
|
730 |
+
* @return int|false
|
731 |
+
*/
|
732 |
public static function frameSizeLookup($frmsizecod, $fscod) {
|
733 |
+
// LSB is whether padding is used or not
|
734 |
+
$padding = (bool) ($frmsizecod & 0x01);
|
735 |
+
$framesizeid = ($frmsizecod & 0x3E) >> 1;
|
736 |
|
737 |
static $frameSizeLookup = array();
|
738 |
if (empty($frameSizeLookup)) {
|
739 |
$frameSizeLookup = array (
|
740 |
+
0 => array( 128, 138, 192), // 32 kbps
|
741 |
+
1 => array( 160, 174, 240), // 40 kbps
|
742 |
+
2 => array( 192, 208, 288), // 48 kbps
|
743 |
+
3 => array( 224, 242, 336), // 56 kbps
|
744 |
+
4 => array( 256, 278, 384), // 64 kbps
|
745 |
+
5 => array( 320, 348, 480), // 80 kbps
|
746 |
+
6 => array( 384, 416, 576), // 96 kbps
|
747 |
+
7 => array( 448, 486, 672), // 112 kbps
|
748 |
+
8 => array( 512, 556, 768), // 128 kbps
|
749 |
+
9 => array( 640, 696, 960), // 160 kbps
|
750 |
+
10 => array( 768, 834, 1152), // 192 kbps
|
751 |
+
11 => array( 896, 974, 1344), // 224 kbps
|
752 |
+
12 => array(1024, 1114, 1536), // 256 kbps
|
753 |
+
13 => array(1280, 1392, 1920), // 320 kbps
|
754 |
+
14 => array(1536, 1670, 2304), // 384 kbps
|
755 |
+
15 => array(1792, 1950, 2688), // 448 kbps
|
756 |
+
16 => array(2048, 2228, 3072), // 512 kbps
|
757 |
+
17 => array(2304, 2506, 3456), // 576 kbps
|
758 |
+
18 => array(2560, 2786, 3840) // 640 kbps
|
759 |
);
|
760 |
}
|
761 |
if (($fscod == 1) && $padding) {
|
765 |
return (isset($frameSizeLookup[$framesizeid][$fscod]) ? $frameSizeLookup[$framesizeid][$fscod] : false);
|
766 |
}
|
767 |
|
768 |
+
/**
|
769 |
+
* @param int $frmsizecod
|
770 |
+
*
|
771 |
+
* @return int|false
|
772 |
+
*/
|
773 |
public static function bitrateLookup($frmsizecod) {
|
774 |
+
// LSB is whether padding is used or not
|
775 |
+
$padding = (bool) ($frmsizecod & 0x01);
|
776 |
+
$framesizeid = ($frmsizecod & 0x3E) >> 1;
|
777 |
|
778 |
static $bitrateLookup = array(
|
779 |
+
0 => 32000,
|
780 |
+
1 => 40000,
|
781 |
+
2 => 48000,
|
782 |
+
3 => 56000,
|
783 |
+
4 => 64000,
|
784 |
+
5 => 80000,
|
785 |
+
6 => 96000,
|
786 |
+
7 => 112000,
|
787 |
+
8 => 128000,
|
788 |
+
9 => 160000,
|
789 |
10 => 192000,
|
790 |
11 => 224000,
|
791 |
12 => 256000,
|
794 |
15 => 448000,
|
795 |
16 => 512000,
|
796 |
17 => 576000,
|
797 |
+
18 => 640000,
|
798 |
);
|
799 |
return (isset($bitrateLookup[$framesizeid]) ? $bitrateLookup[$framesizeid] : false);
|
800 |
}
|
801 |
|
802 |
+
/**
|
803 |
+
* @param int $numblkscod
|
804 |
+
*
|
805 |
+
* @return int|false
|
806 |
+
*/
|
807 |
+
public static function blocksPerSyncFrame($numblkscod) {
|
808 |
+
static $blocksPerSyncFrameLookup = array(
|
809 |
+
0 => 1,
|
810 |
+
1 => 2,
|
811 |
+
2 => 3,
|
812 |
+
3 => 6,
|
813 |
+
);
|
814 |
+
return (isset($blocksPerSyncFrameLookup[$numblkscod]) ? $blocksPerSyncFrameLookup[$numblkscod] : false);
|
815 |
+
}
|
816 |
+
|
817 |
|
818 |
}
|
lib/getid3/module.audio.amr.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.aa.php //
|
@@ -17,7 +17,9 @@
|
|
17 |
|
18 |
class getid3_amr extends getid3_handler
|
19 |
{
|
20 |
-
|
|
|
|
|
21 |
public function Analyze() {
|
22 |
$info = &$this->getid3->info;
|
23 |
|
@@ -26,7 +28,7 @@ class getid3_amr extends getid3_handler
|
|
26 |
|
27 |
$magic = '#!AMR'."\x0A";
|
28 |
if (substr($AMRheader, 0, 6) != $magic) {
|
29 |
-
$
|
30 |
return false;
|
31 |
}
|
32 |
|
@@ -50,7 +52,6 @@ class getid3_amr extends getid3_handler
|
|
50 |
$AMR_frame_header = ord(substr($buffer, 0, 1));
|
51 |
$codec_mode_request = ($AMR_frame_header & 0x78) >> 3; // The 2nd bit through 5th bit (counting the most significant bit as the first bit) comprise the CMR (Codec Mode Request), values 0-7 being valid for AMR. The top bit of the CMR can actually be ignored, though it is used when AMR forms RTP payloads. The lower 3-bits of the header are reserved and are not used. Viewing the header from most significant bit to least significant bit, the encoding is XCCCCXXX, where Xs are reserved (typically 0) and the Cs are the CMR.
|
52 |
if ($codec_mode_request > 7) {
|
53 |
-
$info['error'][] = '';
|
54 |
break;
|
55 |
}
|
56 |
$thisfile_amr['frame_mode_count'][$codec_mode_request]++;
|
@@ -64,7 +65,11 @@ class getid3_amr extends getid3_handler
|
|
64 |
return true;
|
65 |
}
|
66 |
|
67 |
-
|
|
|
|
|
|
|
|
|
68 |
public function amr_mode_bitrate($key) {
|
69 |
static $amr_mode_bitrate = array(
|
70 |
0 => 4750,
|
@@ -79,6 +84,11 @@ class getid3_amr extends getid3_handler
|
|
79 |
return (isset($amr_mode_bitrate[$key]) ? $amr_mode_bitrate[$key] : false);
|
80 |
}
|
81 |
|
|
|
|
|
|
|
|
|
|
|
82 |
public function amr_mode_bytes_per_frame($key) {
|
83 |
static $amr_mode_bitrate = array(
|
84 |
0 => 13, // 1-byte frame header + 95 bits [padded to: 12 bytes] audio data
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.aa.php //
|
17 |
|
18 |
class getid3_amr extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @return bool
|
22 |
+
*/
|
23 |
public function Analyze() {
|
24 |
$info = &$this->getid3->info;
|
25 |
|
28 |
|
29 |
$magic = '#!AMR'."\x0A";
|
30 |
if (substr($AMRheader, 0, 6) != $magic) {
|
31 |
+
$this->error('Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($AMRheader, 0, 6)).'"');
|
32 |
return false;
|
33 |
}
|
34 |
|
52 |
$AMR_frame_header = ord(substr($buffer, 0, 1));
|
53 |
$codec_mode_request = ($AMR_frame_header & 0x78) >> 3; // The 2nd bit through 5th bit (counting the most significant bit as the first bit) comprise the CMR (Codec Mode Request), values 0-7 being valid for AMR. The top bit of the CMR can actually be ignored, though it is used when AMR forms RTP payloads. The lower 3-bits of the header are reserved and are not used. Viewing the header from most significant bit to least significant bit, the encoding is XCCCCXXX, where Xs are reserved (typically 0) and the Cs are the CMR.
|
54 |
if ($codec_mode_request > 7) {
|
|
|
55 |
break;
|
56 |
}
|
57 |
$thisfile_amr['frame_mode_count'][$codec_mode_request]++;
|
65 |
return true;
|
66 |
}
|
67 |
|
68 |
+
/**
|
69 |
+
* @param int $key
|
70 |
+
*
|
71 |
+
* @return int|false
|
72 |
+
*/
|
73 |
public function amr_mode_bitrate($key) {
|
74 |
static $amr_mode_bitrate = array(
|
75 |
0 => 4750,
|
84 |
return (isset($amr_mode_bitrate[$key]) ? $amr_mode_bitrate[$key] : false);
|
85 |
}
|
86 |
|
87 |
+
/**
|
88 |
+
* @param int $key
|
89 |
+
*
|
90 |
+
* @return int|false
|
91 |
+
*/
|
92 |
public function amr_mode_bytes_per_frame($key) {
|
93 |
static $amr_mode_bitrate = array(
|
94 |
0 => 13, // 1-byte frame header + 95 bits [padded to: 12 bytes] audio data
|
lib/getid3/module.audio.au.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.au.php //
|
@@ -17,7 +17,9 @@
|
|
17 |
|
18 |
class getid3_au extends getid3_handler
|
19 |
{
|
20 |
-
|
|
|
|
|
21 |
public function Analyze() {
|
22 |
$info = &$this->getid3->info;
|
23 |
|
@@ -26,7 +28,7 @@ class getid3_au extends getid3_handler
|
|
26 |
|
27 |
$magic = '.snd';
|
28 |
if (substr($AUheader, 0, 4) != $magic) {
|
29 |
-
$
|
30 |
return false;
|
31 |
}
|
32 |
|
@@ -61,7 +63,7 @@ class getid3_au extends getid3_handler
|
|
61 |
$info['audio']['channels'] = $thisfile_au['channels'];
|
62 |
|
63 |
if (($info['avdataoffset'] + $thisfile_au['data_size']) > $info['avdataend']) {
|
64 |
-
$
|
65 |
}
|
66 |
|
67 |
$info['playtime_seconds'] = $thisfile_au['data_size'] / ($thisfile_au['sample_rate'] * $thisfile_au['channels'] * ($thisfile_au['used_bits_per_sample'] / 8));
|
@@ -70,6 +72,11 @@ class getid3_au extends getid3_handler
|
|
70 |
return true;
|
71 |
}
|
72 |
|
|
|
|
|
|
|
|
|
|
|
73 |
public function AUdataFormatNameLookup($id) {
|
74 |
static $AUdataFormatNameLookup = array(
|
75 |
0 => 'unspecified format',
|
@@ -104,6 +111,11 @@ class getid3_au extends getid3_handler
|
|
104 |
return (isset($AUdataFormatNameLookup[$id]) ? $AUdataFormatNameLookup[$id] : false);
|
105 |
}
|
106 |
|
|
|
|
|
|
|
|
|
|
|
107 |
public function AUdataFormatBitsPerSampleLookup($id) {
|
108 |
static $AUdataFormatBitsPerSampleLookup = array(
|
109 |
1 => 8,
|
@@ -132,6 +144,11 @@ class getid3_au extends getid3_handler
|
|
132 |
return (isset($AUdataFormatBitsPerSampleLookup[$id]) ? $AUdataFormatBitsPerSampleLookup[$id] : false);
|
133 |
}
|
134 |
|
|
|
|
|
|
|
|
|
|
|
135 |
public function AUdataFormatUsedBitsPerSampleLookup($id) {
|
136 |
static $AUdataFormatUsedBitsPerSampleLookup = array(
|
137 |
1 => 8,
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.au.php //
|
17 |
|
18 |
class getid3_au extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @return bool
|
22 |
+
*/
|
23 |
public function Analyze() {
|
24 |
$info = &$this->getid3->info;
|
25 |
|
28 |
|
29 |
$magic = '.snd';
|
30 |
if (substr($AUheader, 0, 4) != $magic) {
|
31 |
+
$this->error('Expecting "'.getid3_lib::PrintHexBytes($magic).'" (".snd") at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($AUheader, 0, 4)).'"');
|
32 |
return false;
|
33 |
}
|
34 |
|
63 |
$info['audio']['channels'] = $thisfile_au['channels'];
|
64 |
|
65 |
if (($info['avdataoffset'] + $thisfile_au['data_size']) > $info['avdataend']) {
|
66 |
+
$this->warning('Possible truncated file - expecting "'.$thisfile_au['data_size'].'" bytes of audio data, only found '.($info['avdataend'] - $info['avdataoffset']).' bytes"');
|
67 |
}
|
68 |
|
69 |
$info['playtime_seconds'] = $thisfile_au['data_size'] / ($thisfile_au['sample_rate'] * $thisfile_au['channels'] * ($thisfile_au['used_bits_per_sample'] / 8));
|
72 |
return true;
|
73 |
}
|
74 |
|
75 |
+
/**
|
76 |
+
* @param int $id
|
77 |
+
*
|
78 |
+
* @return string|false
|
79 |
+
*/
|
80 |
public function AUdataFormatNameLookup($id) {
|
81 |
static $AUdataFormatNameLookup = array(
|
82 |
0 => 'unspecified format',
|
111 |
return (isset($AUdataFormatNameLookup[$id]) ? $AUdataFormatNameLookup[$id] : false);
|
112 |
}
|
113 |
|
114 |
+
/**
|
115 |
+
* @param int $id
|
116 |
+
*
|
117 |
+
* @return int|false
|
118 |
+
*/
|
119 |
public function AUdataFormatBitsPerSampleLookup($id) {
|
120 |
static $AUdataFormatBitsPerSampleLookup = array(
|
121 |
1 => 8,
|
144 |
return (isset($AUdataFormatBitsPerSampleLookup[$id]) ? $AUdataFormatBitsPerSampleLookup[$id] : false);
|
145 |
}
|
146 |
|
147 |
+
/**
|
148 |
+
* @param int $id
|
149 |
+
*
|
150 |
+
* @return int|false
|
151 |
+
*/
|
152 |
public function AUdataFormatUsedBitsPerSampleLookup($id) {
|
153 |
static $AUdataFormatUsedBitsPerSampleLookup = array(
|
154 |
1 => 8,
|
lib/getid3/module.audio.avr.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.avr.php //
|
@@ -17,7 +17,9 @@
|
|
17 |
|
18 |
class getid3_avr extends getid3_handler
|
19 |
{
|
20 |
-
|
|
|
|
|
21 |
public function Analyze() {
|
22 |
$info = &$this->getid3->info;
|
23 |
|
@@ -69,7 +71,7 @@ class getid3_avr extends getid3_handler
|
|
69 |
$info['avr']['raw']['magic'] = substr($AVRheader, 0, 4);
|
70 |
$magic = '2BIT';
|
71 |
if ($info['avr']['raw']['magic'] != $magic) {
|
72 |
-
$
|
73 |
unset($info['fileformat']);
|
74 |
unset($info['avr']);
|
75 |
return false;
|
@@ -106,7 +108,7 @@ class getid3_avr extends getid3_handler
|
|
106 |
}
|
107 |
|
108 |
if (($info['avdataend'] - $info['avdataoffset']) != ($info['avr']['sample_length'] * (($info['avr']['bits_per_sample'] == 8) ? 1 : 2))) {
|
109 |
-
$
|
110 |
}
|
111 |
|
112 |
$info['audio']['dataformat'] = 'avr';
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.avr.php //
|
17 |
|
18 |
class getid3_avr extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @return bool
|
22 |
+
*/
|
23 |
public function Analyze() {
|
24 |
$info = &$this->getid3->info;
|
25 |
|
71 |
$info['avr']['raw']['magic'] = substr($AVRheader, 0, 4);
|
72 |
$magic = '2BIT';
|
73 |
if ($info['avr']['raw']['magic'] != $magic) {
|
74 |
+
$this->error('Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($info['avr']['raw']['magic']).'"');
|
75 |
unset($info['fileformat']);
|
76 |
unset($info['avr']);
|
77 |
return false;
|
108 |
}
|
109 |
|
110 |
if (($info['avdataend'] - $info['avdataoffset']) != ($info['avr']['sample_length'] * (($info['avr']['bits_per_sample'] == 8) ? 1 : 2))) {
|
111 |
+
$this->warning('Probable truncated file: expecting '.($info['avr']['sample_length'] * (($info['avr']['bits_per_sample'] == 8) ? 1 : 2)).' bytes of audio data, found '.($info['avdataend'] - $info['avdataoffset']));
|
112 |
}
|
113 |
|
114 |
$info['audio']['dataformat'] = 'avr';
|
lib/getid3/module.audio.bonk.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.la.php //
|
@@ -17,6 +17,9 @@
|
|
17 |
|
18 |
class getid3_bonk extends getid3_handler
|
19 |
{
|
|
|
|
|
|
|
20 |
public function Analyze() {
|
21 |
$info = &$this->getid3->info;
|
22 |
|
@@ -29,7 +32,7 @@ class getid3_bonk extends getid3_handler
|
|
29 |
|
30 |
if (!getid3_lib::intValueSupported($thisfile_bonk['dataend'])) {
|
31 |
|
32 |
-
$
|
33 |
|
34 |
} else {
|
35 |
|
@@ -42,7 +45,7 @@ class getid3_bonk extends getid3_handler
|
|
42 |
$BonkTagOffset = $this->ftell();
|
43 |
$TagHeaderTest = $this->fread(5);
|
44 |
if (($TagHeaderTest{0} != "\x00") || (substr($PossibleBonkTag, 4, 4) != strtolower(substr($PossibleBonkTag, 4, 4)))) {
|
45 |
-
$
|
46 |
return false;
|
47 |
}
|
48 |
$BonkTagName = substr($TagHeaderTest, 1, 4);
|
@@ -114,6 +117,9 @@ class getid3_bonk extends getid3_handler
|
|
114 |
|
115 |
}
|
116 |
|
|
|
|
|
|
|
117 |
public function HandleBonkTags($BonkTagName) {
|
118 |
$info = &$this->getid3->info;
|
119 |
switch ($BonkTagName) {
|
@@ -207,12 +213,18 @@ class getid3_bonk extends getid3_handler
|
|
207 |
break;
|
208 |
|
209 |
default:
|
210 |
-
$
|
211 |
break;
|
212 |
|
213 |
}
|
214 |
}
|
215 |
|
|
|
|
|
|
|
|
|
|
|
|
|
216 |
public static function BonkIsValidTagName($PossibleBonkTag, $ignorecase=false) {
|
217 |
static $BonkIsValidTagName = array('BONK', 'INFO', ' ID3', 'META');
|
218 |
foreach ($BonkIsValidTagName as $validtagname) {
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.la.php //
|
17 |
|
18 |
class getid3_bonk extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @return bool
|
22 |
+
*/
|
23 |
public function Analyze() {
|
24 |
$info = &$this->getid3->info;
|
25 |
|
32 |
|
33 |
if (!getid3_lib::intValueSupported($thisfile_bonk['dataend'])) {
|
34 |
|
35 |
+
$this->warning('Unable to parse BONK file from end (v0.6+ preferred method) because PHP filesystem functions only support up to '.round(PHP_INT_MAX / 1073741824).'GB');
|
36 |
|
37 |
} else {
|
38 |
|
45 |
$BonkTagOffset = $this->ftell();
|
46 |
$TagHeaderTest = $this->fread(5);
|
47 |
if (($TagHeaderTest{0} != "\x00") || (substr($PossibleBonkTag, 4, 4) != strtolower(substr($PossibleBonkTag, 4, 4)))) {
|
48 |
+
$this->error('Expecting "'.getid3_lib::PrintHexBytes("\x00".strtoupper(substr($PossibleBonkTag, 4, 4))).'" at offset '.$BonkTagOffset.', found "'.getid3_lib::PrintHexBytes($TagHeaderTest).'"');
|
49 |
return false;
|
50 |
}
|
51 |
$BonkTagName = substr($TagHeaderTest, 1, 4);
|
117 |
|
118 |
}
|
119 |
|
120 |
+
/**
|
121 |
+
* @param string $BonkTagName
|
122 |
+
*/
|
123 |
public function HandleBonkTags($BonkTagName) {
|
124 |
$info = &$this->getid3->info;
|
125 |
switch ($BonkTagName) {
|
213 |
break;
|
214 |
|
215 |
default:
|
216 |
+
$this->warning('Unexpected Bonk tag "'.$BonkTagName.'" at offset '.$info['bonk'][$BonkTagName]['offset']);
|
217 |
break;
|
218 |
|
219 |
}
|
220 |
}
|
221 |
|
222 |
+
/**
|
223 |
+
* @param string $PossibleBonkTag
|
224 |
+
* @param bool $ignorecase
|
225 |
+
*
|
226 |
+
* @return bool
|
227 |
+
*/
|
228 |
public static function BonkIsValidTagName($PossibleBonkTag, $ignorecase=false) {
|
229 |
static $BonkIsValidTagName = array('BONK', 'INFO', ' ID3', 'META');
|
230 |
foreach ($BonkIsValidTagName as $validtagname) {
|
lib/getid3/module.audio.dsf.php
ADDED
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/////////////////////////////////////////////////////////////////
|
4 |
+
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
9 |
+
/////////////////////////////////////////////////////////////////
|
10 |
+
// //
|
11 |
+
// module.audio.dsf.php //
|
12 |
+
// module for analyzing dsf/DSF Audio files //
|
13 |
+
// dependencies: module.tag.id3v2.php //
|
14 |
+
// ///
|
15 |
+
/////////////////////////////////////////////////////////////////
|
16 |
+
|
17 |
+
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
|
18 |
+
|
19 |
+
class getid3_dsf extends getid3_handler
|
20 |
+
{
|
21 |
+
/**
|
22 |
+
* @return bool
|
23 |
+
*/
|
24 |
+
public function Analyze() {
|
25 |
+
$info = &$this->getid3->info;
|
26 |
+
|
27 |
+
$info['fileformat'] = 'dsf';
|
28 |
+
$info['audio']['dataformat'] = 'dsf';
|
29 |
+
$info['audio']['lossless'] = true;
|
30 |
+
$info['audio']['bitrate_mode'] = 'cbr';
|
31 |
+
|
32 |
+
$this->fseek($info['avdataoffset']);
|
33 |
+
$dsfheader = $this->fread(28 + 12);
|
34 |
+
|
35 |
+
$headeroffset = 0;
|
36 |
+
$info['dsf']['dsd']['magic'] = substr($dsfheader, $headeroffset, 4);
|
37 |
+
$headeroffset += 4;
|
38 |
+
$magic = 'DSD ';
|
39 |
+
if ($info['dsf']['dsd']['magic'] != $magic) {
|
40 |
+
$this->error('Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($info['dsf']['dsd']['magic']).'"');
|
41 |
+
unset($info['fileformat']);
|
42 |
+
unset($info['audio']);
|
43 |
+
unset($info['dsf']);
|
44 |
+
return false;
|
45 |
+
}
|
46 |
+
$info['dsf']['dsd']['dsd_chunk_size'] = getid3_lib::LittleEndian2Int(substr($dsfheader, $headeroffset, 8)); // should be 28
|
47 |
+
$headeroffset += 8;
|
48 |
+
$info['dsf']['dsd']['dsf_file_size'] = getid3_lib::LittleEndian2Int(substr($dsfheader, $headeroffset, 8));
|
49 |
+
$headeroffset += 8;
|
50 |
+
$info['dsf']['dsd']['meta_chunk_offset'] = getid3_lib::LittleEndian2Int(substr($dsfheader, $headeroffset, 8));
|
51 |
+
$headeroffset += 8;
|
52 |
+
|
53 |
+
|
54 |
+
$info['dsf']['fmt']['magic'] = substr($dsfheader, $headeroffset, 4);
|
55 |
+
$headeroffset += 4;
|
56 |
+
$magic = 'fmt ';
|
57 |
+
if ($info['dsf']['fmt']['magic'] != $magic) {
|
58 |
+
$this->error('Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$headeroffset.', found "'.getid3_lib::PrintHexBytes($info['dsf']['fmt']['magic']).'"');
|
59 |
+
return false;
|
60 |
+
}
|
61 |
+
$info['dsf']['fmt']['fmt_chunk_size'] = getid3_lib::LittleEndian2Int(substr($dsfheader, $headeroffset, 8)); // usually 52 bytes
|
62 |
+
$headeroffset += 8;
|
63 |
+
$dsfheader .= $this->fread($info['dsf']['fmt']['fmt_chunk_size'] - 12 + 12); // we have already read the entire DSD chunk, plus 12 bytes of FMT. We now want to read the size of FMT, plus 12 bytes into the next chunk to get magic and size.
|
64 |
+
if (strlen($dsfheader) != ($info['dsf']['dsd']['dsd_chunk_size'] + $info['dsf']['fmt']['fmt_chunk_size'] + 12)) {
|
65 |
+
$this->error('Expecting '.($info['dsf']['dsd']['dsd_chunk_size'] + $info['dsf']['fmt']['fmt_chunk_size']).' bytes header, found '.strlen($dsfheader).' bytes');
|
66 |
+
return false;
|
67 |
+
}
|
68 |
+
$info['dsf']['fmt']['format_version'] = getid3_lib::LittleEndian2Int(substr($dsfheader, $headeroffset, 4)); // usually "1"
|
69 |
+
$headeroffset += 4;
|
70 |
+
$info['dsf']['fmt']['format_id'] = getid3_lib::LittleEndian2Int(substr($dsfheader, $headeroffset, 4)); // usually "0" = "DSD Raw"
|
71 |
+
$headeroffset += 4;
|
72 |
+
$info['dsf']['fmt']['channel_type_id'] = getid3_lib::LittleEndian2Int(substr($dsfheader, $headeroffset, 4));
|
73 |
+
$headeroffset += 4;
|
74 |
+
$info['dsf']['fmt']['channels'] = getid3_lib::LittleEndian2Int(substr($dsfheader, $headeroffset, 4));
|
75 |
+
$headeroffset += 4;
|
76 |
+
$info['dsf']['fmt']['sample_rate'] = getid3_lib::LittleEndian2Int(substr($dsfheader, $headeroffset, 4));
|
77 |
+
$headeroffset += 4;
|
78 |
+
$info['dsf']['fmt']['bits_per_sample'] = getid3_lib::LittleEndian2Int(substr($dsfheader, $headeroffset, 4));
|
79 |
+
$headeroffset += 4;
|
80 |
+
$info['dsf']['fmt']['sample_count'] = getid3_lib::LittleEndian2Int(substr($dsfheader, $headeroffset, 8));
|
81 |
+
$headeroffset += 8;
|
82 |
+
$info['dsf']['fmt']['channel_block_size'] = getid3_lib::LittleEndian2Int(substr($dsfheader, $headeroffset, 4));
|
83 |
+
$headeroffset += 4;
|
84 |
+
$info['dsf']['fmt']['reserved'] = getid3_lib::LittleEndian2Int(substr($dsfheader, $headeroffset, 4)); // zero-filled
|
85 |
+
$headeroffset += 4;
|
86 |
+
|
87 |
+
|
88 |
+
$info['dsf']['data']['magic'] = substr($dsfheader, $headeroffset, 4);
|
89 |
+
$headeroffset += 4;
|
90 |
+
$magic = 'data';
|
91 |
+
if ($info['dsf']['data']['magic'] != $magic) {
|
92 |
+
$this->error('Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$headeroffset.', found "'.getid3_lib::PrintHexBytes($info['dsf']['data']['magic']).'"');
|
93 |
+
return false;
|
94 |
+
}
|
95 |
+
$info['dsf']['data']['data_chunk_size'] = getid3_lib::LittleEndian2Int(substr($dsfheader, $headeroffset, 8));
|
96 |
+
$headeroffset += 8;
|
97 |
+
$info['avdataoffset'] = $headeroffset;
|
98 |
+
$info['avdataend'] = $info['avdataoffset'] + $info['dsf']['data']['data_chunk_size'];
|
99 |
+
|
100 |
+
|
101 |
+
if ($info['dsf']['dsd']['meta_chunk_offset'] > 0) {
|
102 |
+
$getid3_id3v2 = new getid3_id3v2($this->getid3);
|
103 |
+
$getid3_id3v2->StartingOffset = $info['dsf']['dsd']['meta_chunk_offset'];
|
104 |
+
$getid3_id3v2->Analyze();
|
105 |
+
unset($getid3_id3v2);
|
106 |
+
}
|
107 |
+
|
108 |
+
|
109 |
+
$info['dsf']['fmt']['channel_type'] = $this->DSFchannelTypeLookup($info['dsf']['fmt']['channel_type_id']);
|
110 |
+
$info['audio']['channelmode'] = $info['dsf']['fmt']['channel_type'];
|
111 |
+
$info['audio']['bits_per_sample'] = $info['dsf']['fmt']['bits_per_sample'];
|
112 |
+
$info['audio']['sample_rate'] = $info['dsf']['fmt']['sample_rate'];
|
113 |
+
$info['audio']['channels'] = $info['dsf']['fmt']['channels'];
|
114 |
+
$info['audio']['bitrate'] = $info['audio']['bits_per_sample'] * $info['audio']['sample_rate'] * $info['audio']['channels'];
|
115 |
+
$info['playtime_seconds'] = ($info['dsf']['data']['data_chunk_size'] * 8) / $info['audio']['bitrate'];
|
116 |
+
|
117 |
+
return true;
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* @param int $channel_type_id
|
122 |
+
*
|
123 |
+
* @return string
|
124 |
+
*/
|
125 |
+
public static function DSFchannelTypeLookup($channel_type_id) {
|
126 |
+
static $DSFchannelTypeLookup = array(
|
127 |
+
// interleaving order:
|
128 |
+
1 => 'mono', // 1: Mono
|
129 |
+
2 => 'stereo', // 1: Front-Left; 2: Front-Right
|
130 |
+
3 => '3-channel', // 1: Front-Left; 2: Front-Right; 3: Center
|
131 |
+
4 => 'quad', // 1: Front-Left; 2: Front-Right; 3: Back-Left; 4: Back-Right
|
132 |
+
5 => '4-channel', // 1: Front-Left; 2: Front-Right; 3: Center; 4: Low-Frequency
|
133 |
+
6 => '5-channel', // 1: Front-Left; 2: Front-Right; 3: Center; 4: Back-Left 5: Back-Right
|
134 |
+
7 => '5.1', // 1: Front-Left; 2: Front-Right; 3: Center; 4: Low-Frequency; 5: Back-Left; 6: Back-Right
|
135 |
+
);
|
136 |
+
return (isset($DSFchannelTypeLookup[$channel_type_id]) ? $DSFchannelTypeLookup[$channel_type_id] : '');
|
137 |
+
}
|
138 |
+
|
139 |
+
}
|
lib/getid3/module.audio.dss.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.dss.php //
|
@@ -17,15 +17,17 @@
|
|
17 |
|
18 |
class getid3_dss extends getid3_handler
|
19 |
{
|
20 |
-
|
|
|
|
|
21 |
public function Analyze() {
|
22 |
$info = &$this->getid3->info;
|
23 |
|
24 |
$this->fseek($info['avdataoffset']);
|
25 |
$DSSheader = $this->fread(1540);
|
26 |
|
27 |
-
if (!preg_match('#^
|
28 |
-
$
|
29 |
return false;
|
30 |
}
|
31 |
|
@@ -38,33 +40,44 @@ class getid3_dss extends getid3_handler
|
|
38 |
$info['audio']['dataformat'] = substr($DSSheader, 1, 3); // "dss" or "ds2"
|
39 |
$info['audio']['bitrate_mode'] = 'cbr';
|
40 |
|
41 |
-
$info['dss']['version']
|
42 |
-
$info['dss']['hardware']
|
43 |
-
$info['dss']['unknown1']
|
44 |
// 32-37 = "FE FF FE FF F7 FF" in all the sample files I've seen
|
45 |
-
$info['dss']['
|
46 |
-
$info['dss']['
|
47 |
-
$info['dss']['playtime_sec']
|
48 |
-
$info['dss']['
|
49 |
-
|
50 |
-
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
52 |
|
53 |
$info['audio']['bits_per_sample'] = 16; // maybe, maybe not -- most compressed audio formats don't have a fixed bits-per-sample value, but this is a reasonable approximation
|
54 |
-
$info['audio']['sample_rate'] = $this->DSSsampleRateLookup($info['dss']['sample_rate_index']);
|
55 |
$info['audio']['channels'] = 1;
|
56 |
|
57 |
-
$info['
|
58 |
-
|
59 |
-
|
60 |
$info['playtime_seconds'] = $info['dss']['playtime_sec'];
|
61 |
-
|
|
|
|
|
62 |
}
|
63 |
$info['audio']['bitrate'] = ($info['filesize'] * 8) / $info['playtime_seconds'];
|
64 |
|
65 |
return true;
|
66 |
}
|
67 |
|
|
|
|
|
|
|
|
|
|
|
68 |
public function DSSdateStringToUnixDate($datestring) {
|
69 |
$y = substr($datestring, 0, 2);
|
70 |
$m = substr($datestring, 2, 2);
|
@@ -76,6 +89,11 @@ class getid3_dss extends getid3_handler
|
|
76 |
return mktime($h, $i, $s, $m, $d, $y);
|
77 |
}
|
78 |
|
|
|
|
|
|
|
|
|
|
|
79 |
public function DSSsampleRateLookup($sample_rate_index) {
|
80 |
static $dssSampleRateLookup = array(
|
81 |
0x0A => 16000,
|
@@ -84,7 +102,7 @@ class getid3_dss extends getid3_handler
|
|
84 |
0x15 => 8000,
|
85 |
);
|
86 |
if (!array_key_exists($sample_rate_index, $dssSampleRateLookup)) {
|
87 |
-
$this->getid3->warning('unknown sample_rate_index: '
|
88 |
return false;
|
89 |
}
|
90 |
return $dssSampleRateLookup[$sample_rate_index];
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.dss.php //
|
17 |
|
18 |
class getid3_dss extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @return bool
|
22 |
+
*/
|
23 |
public function Analyze() {
|
24 |
$info = &$this->getid3->info;
|
25 |
|
26 |
$this->fseek($info['avdataoffset']);
|
27 |
$DSSheader = $this->fread(1540);
|
28 |
|
29 |
+
if (!preg_match('#^[\\x02-\\x06]ds[s2]#', $DSSheader)) {
|
30 |
+
$this->error('Expecting "[02-06] 64 73 [73|32]" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($DSSheader, 0, 4)).'"');
|
31 |
return false;
|
32 |
}
|
33 |
|
40 |
$info['audio']['dataformat'] = substr($DSSheader, 1, 3); // "dss" or "ds2"
|
41 |
$info['audio']['bitrate_mode'] = 'cbr';
|
42 |
|
43 |
+
$info['dss']['version'] = ord(substr($DSSheader, 0, 1));
|
44 |
+
$info['dss']['hardware'] = trim(substr($DSSheader, 12, 16)); // identification string for hardware used to create the file, e.g. "DPM 9600", "DS2400"
|
45 |
+
$info['dss']['unknown1'] = getid3_lib::LittleEndian2Int(substr($DSSheader, 28, 4));
|
46 |
// 32-37 = "FE FF FE FF F7 FF" in all the sample files I've seen
|
47 |
+
$info['dss']['date_create_unix'] = $this->DSSdateStringToUnixDate(substr($DSSheader, 38, 12));
|
48 |
+
$info['dss']['date_complete_unix'] = $this->DSSdateStringToUnixDate(substr($DSSheader, 50, 12));
|
49 |
+
$info['dss']['playtime_sec'] = intval((substr($DSSheader, 62, 2) * 3600) + (substr($DSSheader, 64, 2) * 60) + substr($DSSheader, 66, 2)); // approximate file playtime in HHMMSS
|
50 |
+
if ($info['dss']['version'] <= 3) {
|
51 |
+
$info['dss']['playtime_ms'] = getid3_lib::LittleEndian2Int(substr($DSSheader, 512, 4)); // exact file playtime in milliseconds. Has also been observed at offset 530 in one sample file, with something else (unknown) at offset 512
|
52 |
+
$info['dss']['priority'] = ord(substr($DSSheader, 793, 1));
|
53 |
+
$info['dss']['comments'] = trim(substr($DSSheader, 798, 100));
|
54 |
+
$info['dss']['sample_rate_index'] = ord(substr($DSSheader, 1538, 1)); // this isn't certain, this may or may not be where the sample rate info is stored, but it seems consistent on my small selection of sample files
|
55 |
+
$info['audio']['sample_rate'] = $this->DSSsampleRateLookup($info['dss']['sample_rate_index']);
|
56 |
+
} else {
|
57 |
+
$this->getid3->warning('DSS above version 3 not fully supported in this version of getID3. Any additional documentation or format specifications would be welcome. This file is version '.$info['dss']['version']);
|
58 |
+
}
|
59 |
|
60 |
$info['audio']['bits_per_sample'] = 16; // maybe, maybe not -- most compressed audio formats don't have a fixed bits-per-sample value, but this is a reasonable approximation
|
|
|
61 |
$info['audio']['channels'] = 1;
|
62 |
|
63 |
+
if (!empty($info['dss']['playtime_ms']) && (floor($info['dss']['playtime_ms'] / 1000) == $info['dss']['playtime_sec'])) { // *should* just be playtime_ms / 1000 but at least one sample file has playtime_ms at offset 530 instead of offset 512, so safety check
|
64 |
+
$info['playtime_seconds'] = $info['dss']['playtime_ms'] / 1000;
|
65 |
+
} else {
|
66 |
$info['playtime_seconds'] = $info['dss']['playtime_sec'];
|
67 |
+
if (!empty($info['dss']['playtime_ms'])) {
|
68 |
+
$this->getid3->warning('playtime_ms ('.number_format($info['dss']['playtime_ms'] / 1000, 3).') does not match playtime_sec ('.number_format($info['dss']['playtime_sec']).') - using playtime_sec value');
|
69 |
+
}
|
70 |
}
|
71 |
$info['audio']['bitrate'] = ($info['filesize'] * 8) / $info['playtime_seconds'];
|
72 |
|
73 |
return true;
|
74 |
}
|
75 |
|
76 |
+
/**
|
77 |
+
* @param string $datestring
|
78 |
+
*
|
79 |
+
* @return int|false
|
80 |
+
*/
|
81 |
public function DSSdateStringToUnixDate($datestring) {
|
82 |
$y = substr($datestring, 0, 2);
|
83 |
$m = substr($datestring, 2, 2);
|
89 |
return mktime($h, $i, $s, $m, $d, $y);
|
90 |
}
|
91 |
|
92 |
+
/**
|
93 |
+
* @param int $sample_rate_index
|
94 |
+
*
|
95 |
+
* @return int|false
|
96 |
+
*/
|
97 |
public function DSSsampleRateLookup($sample_rate_index) {
|
98 |
static $dssSampleRateLookup = array(
|
99 |
0x0A => 16000,
|
102 |
0x15 => 8000,
|
103 |
);
|
104 |
if (!array_key_exists($sample_rate_index, $dssSampleRateLookup)) {
|
105 |
+
$this->getid3->warning('unknown sample_rate_index: 0x'.strtoupper(dechex($sample_rate_index)));
|
106 |
return false;
|
107 |
}
|
108 |
return $dssSampleRateLookup[$sample_rate_index];
|
lib/getid3/module.audio.dts.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.dts.php //
|
@@ -21,21 +21,27 @@
|
|
21 |
class getid3_dts extends getid3_handler
|
22 |
{
|
23 |
/**
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
|
|
|
|
|
|
|
28 |
private $readBinDataOffset = 0;
|
29 |
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
|
|
|
|
|
|
|
39 |
public function Analyze() {
|
40 |
$info = &$this->getid3->info;
|
41 |
$info['fileformat'] = 'dts';
|
@@ -45,18 +51,18 @@ class getid3_dts extends getid3_handler
|
|
45 |
|
46 |
// check syncword
|
47 |
$sync = substr($DTSheader, 0, 4);
|
48 |
-
|
49 |
|
50 |
-
|
51 |
$this->readBinDataOffset = 32;
|
52 |
|
53 |
-
|
54 |
|
55 |
// Matroska contains DTS without syncword encoded as raw big-endian format
|
56 |
$encoding = 0;
|
57 |
$this->readBinDataOffset = 0;
|
58 |
|
59 |
-
|
60 |
|
61 |
unset($info['fileformat']);
|
62 |
return $this->error('Expecting "'.implode('| ', array_map('getid3_lib::PrintHexBytes', self::$syncwords)).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($sync).'"');
|
@@ -139,6 +145,12 @@ class getid3_dts extends getid3_handler
|
|
139 |
return true;
|
140 |
}
|
141 |
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
private function readBinData($bin, $length) {
|
143 |
$data = substr($bin, $this->readBinDataOffset, $length);
|
144 |
$this->readBinDataOffset += $length;
|
@@ -146,6 +158,11 @@ class getid3_dts extends getid3_handler
|
|
146 |
return bindec($data);
|
147 |
}
|
148 |
|
|
|
|
|
|
|
|
|
|
|
149 |
public static function bitrateLookup($index) {
|
150 |
static $lookup = array(
|
151 |
0 => 32000,
|
@@ -184,6 +201,11 @@ class getid3_dts extends getid3_handler
|
|
184 |
return (isset($lookup[$index]) ? $lookup[$index] : false);
|
185 |
}
|
186 |
|
|
|
|
|
|
|
|
|
|
|
187 |
public static function sampleRateLookup($index) {
|
188 |
static $lookup = array(
|
189 |
0 => 'invalid',
|
@@ -206,6 +228,11 @@ class getid3_dts extends getid3_handler
|
|
206 |
return (isset($lookup[$index]) ? $lookup[$index] : false);
|
207 |
}
|
208 |
|
|
|
|
|
|
|
|
|
|
|
209 |
public static function bitPerSampleLookup($index) {
|
210 |
static $lookup = array(
|
211 |
0 => 16,
|
@@ -216,6 +243,11 @@ class getid3_dts extends getid3_handler
|
|
216 |
return (isset($lookup[$index]) ? $lookup[$index] : false);
|
217 |
}
|
218 |
|
|
|
|
|
|
|
|
|
|
|
219 |
public static function numChannelsLookup($index) {
|
220 |
switch ($index) {
|
221 |
case 0:
|
@@ -254,6 +286,11 @@ class getid3_dts extends getid3_handler
|
|
254 |
return false;
|
255 |
}
|
256 |
|
|
|
|
|
|
|
|
|
|
|
257 |
public static function channelArrangementLookup($index) {
|
258 |
static $lookup = array(
|
259 |
0 => 'A',
|
@@ -276,6 +313,12 @@ class getid3_dts extends getid3_handler
|
|
276 |
return (isset($lookup[$index]) ? $lookup[$index] : 'user-defined');
|
277 |
}
|
278 |
|
|
|
|
|
|
|
|
|
|
|
|
|
279 |
public static function dialogNormalization($index, $version) {
|
280 |
switch ($version) {
|
281 |
case 7:
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.dts.php //
|
21 |
class getid3_dts extends getid3_handler
|
22 |
{
|
23 |
/**
|
24 |
+
* Default DTS syncword used in native .cpt or .dts formats.
|
25 |
+
*/
|
26 |
+
const syncword = "\x7F\xFE\x80\x01";
|
27 |
|
28 |
+
/**
|
29 |
+
* @var int
|
30 |
+
*/
|
31 |
private $readBinDataOffset = 0;
|
32 |
|
33 |
+
/**
|
34 |
+
* Possible syncwords indicating bitstream encoding.
|
35 |
+
*/
|
36 |
+
public static $syncwords = array(
|
37 |
+
0 => "\x7F\xFE\x80\x01", // raw big-endian
|
38 |
+
1 => "\xFE\x7F\x01\x80", // raw little-endian
|
39 |
+
2 => "\x1F\xFF\xE8\x00", // 14-bit big-endian
|
40 |
+
3 => "\xFF\x1F\x00\xE8"); // 14-bit little-endian
|
41 |
|
42 |
+
/**
|
43 |
+
* @return bool
|
44 |
+
*/
|
45 |
public function Analyze() {
|
46 |
$info = &$this->getid3->info;
|
47 |
$info['fileformat'] = 'dts';
|
51 |
|
52 |
// check syncword
|
53 |
$sync = substr($DTSheader, 0, 4);
|
54 |
+
if (($encoding = array_search($sync, self::$syncwords)) !== false) {
|
55 |
|
56 |
+
$info['dts']['raw']['magic'] = $sync;
|
57 |
$this->readBinDataOffset = 32;
|
58 |
|
59 |
+
} elseif ($this->isDependencyFor('matroska')) {
|
60 |
|
61 |
// Matroska contains DTS without syncword encoded as raw big-endian format
|
62 |
$encoding = 0;
|
63 |
$this->readBinDataOffset = 0;
|
64 |
|
65 |
+
} else {
|
66 |
|
67 |
unset($info['fileformat']);
|
68 |
return $this->error('Expecting "'.implode('| ', array_map('getid3_lib::PrintHexBytes', self::$syncwords)).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($sync).'"');
|
145 |
return true;
|
146 |
}
|
147 |
|
148 |
+
/**
|
149 |
+
* @param string $bin
|
150 |
+
* @param int $length
|
151 |
+
*
|
152 |
+
* @return float|int
|
153 |
+
*/
|
154 |
private function readBinData($bin, $length) {
|
155 |
$data = substr($bin, $this->readBinDataOffset, $length);
|
156 |
$this->readBinDataOffset += $length;
|
158 |
return bindec($data);
|
159 |
}
|
160 |
|
161 |
+
/**
|
162 |
+
* @param int $index
|
163 |
+
*
|
164 |
+
* @return int|string|false
|
165 |
+
*/
|
166 |
public static function bitrateLookup($index) {
|
167 |
static $lookup = array(
|
168 |
0 => 32000,
|
201 |
return (isset($lookup[$index]) ? $lookup[$index] : false);
|
202 |
}
|
203 |
|
204 |
+
/**
|
205 |
+
* @param int $index
|
206 |
+
*
|
207 |
+
* @return int|string|false
|
208 |
+
*/
|
209 |
public static function sampleRateLookup($index) {
|
210 |
static $lookup = array(
|
211 |
0 => 'invalid',
|
228 |
return (isset($lookup[$index]) ? $lookup[$index] : false);
|
229 |
}
|
230 |
|
231 |
+
/**
|
232 |
+
* @param int $index
|
233 |
+
*
|
234 |
+
* @return int|false
|
235 |
+
*/
|
236 |
public static function bitPerSampleLookup($index) {
|
237 |
static $lookup = array(
|
238 |
0 => 16,
|
243 |
return (isset($lookup[$index]) ? $lookup[$index] : false);
|
244 |
}
|
245 |
|
246 |
+
/**
|
247 |
+
* @param int $index
|
248 |
+
*
|
249 |
+
* @return int|false
|
250 |
+
*/
|
251 |
public static function numChannelsLookup($index) {
|
252 |
switch ($index) {
|
253 |
case 0:
|
286 |
return false;
|
287 |
}
|
288 |
|
289 |
+
/**
|
290 |
+
* @param int $index
|
291 |
+
*
|
292 |
+
* @return string
|
293 |
+
*/
|
294 |
public static function channelArrangementLookup($index) {
|
295 |
static $lookup = array(
|
296 |
0 => 'A',
|
313 |
return (isset($lookup[$index]) ? $lookup[$index] : 'user-defined');
|
314 |
}
|
315 |
|
316 |
+
/**
|
317 |
+
* @param int $index
|
318 |
+
* @param int $version
|
319 |
+
*
|
320 |
+
* @return int|false
|
321 |
+
*/
|
322 |
public static function dialogNormalization($index, $version) {
|
323 |
switch ($version) {
|
324 |
case 7:
|
lib/getid3/module.audio.flac.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.flac.php //
|
@@ -24,6 +24,9 @@ class getid3_flac extends getid3_handler
|
|
24 |
{
|
25 |
const syncword = 'fLaC';
|
26 |
|
|
|
|
|
|
|
27 |
public function Analyze() {
|
28 |
$info = &$this->getid3->info;
|
29 |
|
@@ -41,22 +44,30 @@ class getid3_flac extends getid3_handler
|
|
41 |
return $this->parseMETAdata();
|
42 |
}
|
43 |
|
|
|
|
|
|
|
44 |
public function parseMETAdata() {
|
45 |
$info = &$this->getid3->info;
|
46 |
do {
|
47 |
$BlockOffset = $this->ftell();
|
48 |
$BlockHeader = $this->fread(4);
|
49 |
-
$LBFBT = getid3_lib::BigEndian2Int(substr($BlockHeader, 0, 1));
|
50 |
$LastBlockFlag = (bool) ($LBFBT & 0x80);
|
51 |
$BlockType = ($LBFBT & 0x7F);
|
52 |
$BlockLength = getid3_lib::BigEndian2Int(substr($BlockHeader, 1, 3));
|
53 |
$BlockTypeText = self::metaBlockTypeLookup($BlockType);
|
54 |
|
55 |
if (($BlockOffset + 4 + $BlockLength) > $info['avdataend']) {
|
56 |
-
$this->
|
57 |
break;
|
58 |
}
|
59 |
if ($BlockLength < 1) {
|
|
|
|
|
|
|
|
|
|
|
60 |
$this->error('METADATA_BLOCK_HEADER.BLOCK_LENGTH ('.$BlockLength.') at offset '.$BlockOffset.' is invalid');
|
61 |
break;
|
62 |
}
|
@@ -167,7 +178,7 @@ class getid3_flac extends getid3_handler
|
|
167 |
if (isset($info['flac']['STREAMINFO']['audio_signature'])) {
|
168 |
|
169 |
if ($info['flac']['STREAMINFO']['audio_signature'] === str_repeat("\x00", 16)) {
|
170 |
-
|
171 |
}
|
172 |
else {
|
173 |
$info['md5_data_source'] = '';
|
@@ -194,12 +205,14 @@ class getid3_flac extends getid3_handler
|
|
194 |
return true;
|
195 |
}
|
196 |
|
197 |
-
private function parseSTREAMINFO($BlockData) {
|
198 |
-
$info = &$this->getid3->info;
|
199 |
-
|
200 |
-
$info['flac']['STREAMINFO'] = array();
|
201 |
-
$streaminfo = &$info['flac']['STREAMINFO'];
|
202 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
203 |
$streaminfo['min_block_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 0, 2));
|
204 |
$streaminfo['max_block_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 2, 2));
|
205 |
$streaminfo['min_frame_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 4, 3));
|
@@ -211,15 +224,28 @@ class getid3_flac extends getid3_handler
|
|
211 |
$streaminfo['bits_per_sample'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 23, 5)) + 1;
|
212 |
$streaminfo['samples_stream'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 28, 36));
|
213 |
|
214 |
-
$streaminfo['audio_signature'] =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
215 |
|
216 |
-
|
|
|
|
|
217 |
|
218 |
$info['audio']['bitrate_mode'] = 'vbr';
|
219 |
-
$info['audio']['sample_rate'] = $
|
220 |
-
$info['audio']['channels'] = $
|
221 |
-
$info['audio']['bits_per_sample'] = $
|
222 |
-
$info['playtime_seconds'] = $
|
223 |
if ($info['playtime_seconds'] > 0) {
|
224 |
if (!$this->isDependencyFor('matroska')) {
|
225 |
$info['audio']['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
|
@@ -236,6 +262,11 @@ class getid3_flac extends getid3_handler
|
|
236 |
return true;
|
237 |
}
|
238 |
|
|
|
|
|
|
|
|
|
|
|
239 |
private function parseAPPLICATION($BlockData) {
|
240 |
$info = &$this->getid3->info;
|
241 |
|
@@ -246,6 +277,11 @@ class getid3_flac extends getid3_handler
|
|
246 |
return true;
|
247 |
}
|
248 |
|
|
|
|
|
|
|
|
|
|
|
249 |
private function parseSEEKTABLE($BlockData) {
|
250 |
$info = &$this->getid3->info;
|
251 |
|
@@ -275,6 +311,11 @@ class getid3_flac extends getid3_handler
|
|
275 |
return true;
|
276 |
}
|
277 |
|
|
|
|
|
|
|
|
|
|
|
278 |
private function parseVORBIS_COMMENT($BlockData) {
|
279 |
$info = &$this->getid3->info;
|
280 |
|
@@ -294,6 +335,11 @@ class getid3_flac extends getid3_handler
|
|
294 |
return true;
|
295 |
}
|
296 |
|
|
|
|
|
|
|
|
|
|
|
297 |
private function parseCUESHEET($BlockData) {
|
298 |
$info = &$this->getid3->info;
|
299 |
$offset = 0;
|
@@ -346,9 +392,11 @@ class getid3_flac extends getid3_handler
|
|
346 |
}
|
347 |
|
348 |
/**
|
349 |
-
|
350 |
-
|
351 |
-
|
|
|
|
|
352 |
public function parsePICTURE() {
|
353 |
$info = &$this->getid3->info;
|
354 |
|
@@ -380,6 +428,11 @@ class getid3_flac extends getid3_handler
|
|
380 |
return true;
|
381 |
}
|
382 |
|
|
|
|
|
|
|
|
|
|
|
383 |
public static function metaBlockTypeLookup($blocktype) {
|
384 |
static $lookup = array(
|
385 |
0 => 'STREAMINFO',
|
@@ -393,6 +446,11 @@ class getid3_flac extends getid3_handler
|
|
393 |
return (isset($lookup[$blocktype]) ? $lookup[$blocktype] : 'reserved');
|
394 |
}
|
395 |
|
|
|
|
|
|
|
|
|
|
|
396 |
public static function applicationIDLookup($applicationid) {
|
397 |
// http://flac.sourceforge.net/id.html
|
398 |
static $lookup = array(
|
@@ -423,6 +481,11 @@ class getid3_flac extends getid3_handler
|
|
423 |
return (isset($lookup[$applicationid]) ? $lookup[$applicationid] : 'reserved');
|
424 |
}
|
425 |
|
|
|
|
|
|
|
|
|
|
|
426 |
public static function pictureTypeLookup($type_id) {
|
427 |
static $lookup = array (
|
428 |
0 => 'Other',
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.flac.php //
|
24 |
{
|
25 |
const syncword = 'fLaC';
|
26 |
|
27 |
+
/**
|
28 |
+
* @return bool
|
29 |
+
*/
|
30 |
public function Analyze() {
|
31 |
$info = &$this->getid3->info;
|
32 |
|
44 |
return $this->parseMETAdata();
|
45 |
}
|
46 |
|
47 |
+
/**
|
48 |
+
* @return bool
|
49 |
+
*/
|
50 |
public function parseMETAdata() {
|
51 |
$info = &$this->getid3->info;
|
52 |
do {
|
53 |
$BlockOffset = $this->ftell();
|
54 |
$BlockHeader = $this->fread(4);
|
55 |
+
$LBFBT = getid3_lib::BigEndian2Int(substr($BlockHeader, 0, 1)); // LBFBT = LastBlockFlag + BlockType
|
56 |
$LastBlockFlag = (bool) ($LBFBT & 0x80);
|
57 |
$BlockType = ($LBFBT & 0x7F);
|
58 |
$BlockLength = getid3_lib::BigEndian2Int(substr($BlockHeader, 1, 3));
|
59 |
$BlockTypeText = self::metaBlockTypeLookup($BlockType);
|
60 |
|
61 |
if (($BlockOffset + 4 + $BlockLength) > $info['avdataend']) {
|
62 |
+
$this->warning('METADATA_BLOCK_HEADER.BLOCK_TYPE ('.$BlockTypeText.') at offset '.$BlockOffset.' extends beyond end of file');
|
63 |
break;
|
64 |
}
|
65 |
if ($BlockLength < 1) {
|
66 |
+
if ($BlockTypeText != 'reserved') {
|
67 |
+
// probably supposed to be zero-length
|
68 |
+
$this->warning('METADATA_BLOCK_HEADER.BLOCK_LENGTH ('.$BlockTypeText.') at offset '.$BlockOffset.' is zero bytes');
|
69 |
+
continue;
|
70 |
+
}
|
71 |
$this->error('METADATA_BLOCK_HEADER.BLOCK_LENGTH ('.$BlockLength.') at offset '.$BlockOffset.' is invalid');
|
72 |
break;
|
73 |
}
|
178 |
if (isset($info['flac']['STREAMINFO']['audio_signature'])) {
|
179 |
|
180 |
if ($info['flac']['STREAMINFO']['audio_signature'] === str_repeat("\x00", 16)) {
|
181 |
+
$this->warning('FLAC STREAMINFO.audio_signature is null (known issue with libOggFLAC)');
|
182 |
}
|
183 |
else {
|
184 |
$info['md5_data_source'] = '';
|
205 |
return true;
|
206 |
}
|
207 |
|
|
|
|
|
|
|
|
|
|
|
208 |
|
209 |
+
/**
|
210 |
+
* @param string $BlockData
|
211 |
+
*
|
212 |
+
* @return array
|
213 |
+
*/
|
214 |
+
public static function parseSTREAMINFOdata($BlockData) {
|
215 |
+
$streaminfo = array();
|
216 |
$streaminfo['min_block_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 0, 2));
|
217 |
$streaminfo['max_block_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 2, 2));
|
218 |
$streaminfo['min_frame_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 4, 3));
|
224 |
$streaminfo['bits_per_sample'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 23, 5)) + 1;
|
225 |
$streaminfo['samples_stream'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 28, 36));
|
226 |
|
227 |
+
$streaminfo['audio_signature'] = substr($BlockData, 18, 16);
|
228 |
+
|
229 |
+
return $streaminfo;
|
230 |
+
}
|
231 |
+
|
232 |
+
/**
|
233 |
+
* @param string $BlockData
|
234 |
+
*
|
235 |
+
* @return bool
|
236 |
+
*/
|
237 |
+
private function parseSTREAMINFO($BlockData) {
|
238 |
+
$info = &$this->getid3->info;
|
239 |
|
240 |
+
$info['flac']['STREAMINFO'] = self::parseSTREAMINFOdata($BlockData);
|
241 |
+
|
242 |
+
if (!empty($info['flac']['STREAMINFO']['sample_rate'])) {
|
243 |
|
244 |
$info['audio']['bitrate_mode'] = 'vbr';
|
245 |
+
$info['audio']['sample_rate'] = $info['flac']['STREAMINFO']['sample_rate'];
|
246 |
+
$info['audio']['channels'] = $info['flac']['STREAMINFO']['channels'];
|
247 |
+
$info['audio']['bits_per_sample'] = $info['flac']['STREAMINFO']['bits_per_sample'];
|
248 |
+
$info['playtime_seconds'] = $info['flac']['STREAMINFO']['samples_stream'] / $info['flac']['STREAMINFO']['sample_rate'];
|
249 |
if ($info['playtime_seconds'] > 0) {
|
250 |
if (!$this->isDependencyFor('matroska')) {
|
251 |
$info['audio']['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
|
262 |
return true;
|
263 |
}
|
264 |
|
265 |
+
/**
|
266 |
+
* @param string $BlockData
|
267 |
+
*
|
268 |
+
* @return bool
|
269 |
+
*/
|
270 |
private function parseAPPLICATION($BlockData) {
|
271 |
$info = &$this->getid3->info;
|
272 |
|
277 |
return true;
|
278 |
}
|
279 |
|
280 |
+
/**
|
281 |
+
* @param string $BlockData
|
282 |
+
*
|
283 |
+
* @return bool
|
284 |
+
*/
|
285 |
private function parseSEEKTABLE($BlockData) {
|
286 |
$info = &$this->getid3->info;
|
287 |
|
311 |
return true;
|
312 |
}
|
313 |
|
314 |
+
/**
|
315 |
+
* @param string $BlockData
|
316 |
+
*
|
317 |
+
* @return bool
|
318 |
+
*/
|
319 |
private function parseVORBIS_COMMENT($BlockData) {
|
320 |
$info = &$this->getid3->info;
|
321 |
|
335 |
return true;
|
336 |
}
|
337 |
|
338 |
+
/**
|
339 |
+
* @param string $BlockData
|
340 |
+
*
|
341 |
+
* @return bool
|
342 |
+
*/
|
343 |
private function parseCUESHEET($BlockData) {
|
344 |
$info = &$this->getid3->info;
|
345 |
$offset = 0;
|
392 |
}
|
393 |
|
394 |
/**
|
395 |
+
* Parse METADATA_BLOCK_PICTURE flac structure and extract attachment
|
396 |
+
* External usage: audio.ogg
|
397 |
+
*
|
398 |
+
* @return bool
|
399 |
+
*/
|
400 |
public function parsePICTURE() {
|
401 |
$info = &$this->getid3->info;
|
402 |
|
428 |
return true;
|
429 |
}
|
430 |
|
431 |
+
/**
|
432 |
+
* @param int $blocktype
|
433 |
+
*
|
434 |
+
* @return string
|
435 |
+
*/
|
436 |
public static function metaBlockTypeLookup($blocktype) {
|
437 |
static $lookup = array(
|
438 |
0 => 'STREAMINFO',
|
446 |
return (isset($lookup[$blocktype]) ? $lookup[$blocktype] : 'reserved');
|
447 |
}
|
448 |
|
449 |
+
/**
|
450 |
+
* @param int $applicationid
|
451 |
+
*
|
452 |
+
* @return string
|
453 |
+
*/
|
454 |
public static function applicationIDLookup($applicationid) {
|
455 |
// http://flac.sourceforge.net/id.html
|
456 |
static $lookup = array(
|
481 |
return (isset($lookup[$applicationid]) ? $lookup[$applicationid] : 'reserved');
|
482 |
}
|
483 |
|
484 |
+
/**
|
485 |
+
* @param int $type_id
|
486 |
+
*
|
487 |
+
* @return string
|
488 |
+
*/
|
489 |
public static function pictureTypeLookup($type_id) {
|
490 |
static $lookup = array (
|
491 |
0 => 'Other',
|
lib/getid3/module.audio.la.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.la.php //
|
@@ -18,7 +18,9 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php',
|
|
18 |
|
19 |
class getid3_la extends getid3_handler
|
20 |
{
|
21 |
-
|
|
|
|
|
22 |
public function Analyze() {
|
23 |
$info = &$this->getid3->info;
|
24 |
|
@@ -42,13 +44,13 @@ class getid3_la extends getid3_handler
|
|
42 |
$info['la']['uncompressed_size'] = getid3_lib::LittleEndian2Int(substr($rawdata, $offset, 4));
|
43 |
$offset += 4;
|
44 |
if ($info['la']['uncompressed_size'] == 0) {
|
45 |
-
$
|
46 |
return false;
|
47 |
}
|
48 |
|
49 |
$WAVEchunk = substr($rawdata, $offset, 4);
|
50 |
if ($WAVEchunk !== 'WAVE') {
|
51 |
-
$
|
52 |
return false;
|
53 |
}
|
54 |
$offset += 4;
|
@@ -69,7 +71,7 @@ class getid3_la extends getid3_handler
|
|
69 |
|
70 |
$fmt_chunk = substr($rawdata, $offset, 4);
|
71 |
if ($fmt_chunk !== 'fmt ') {
|
72 |
-
$
|
73 |
return false;
|
74 |
}
|
75 |
$offset += 4;
|
@@ -82,14 +84,14 @@ class getid3_la extends getid3_handler
|
|
82 |
$info['la']['channels'] = getid3_lib::LittleEndian2Int(substr($rawdata, $offset, 2));
|
83 |
$offset += 2;
|
84 |
if ($info['la']['channels'] == 0) {
|
85 |
-
$
|
86 |
return false;
|
87 |
}
|
88 |
|
89 |
$info['la']['sample_rate'] = getid3_lib::LittleEndian2Int(substr($rawdata, $offset, 4));
|
90 |
$offset += 4;
|
91 |
if ($info['la']['sample_rate'] == 0) {
|
92 |
-
$
|
93 |
return false;
|
94 |
}
|
95 |
|
@@ -146,7 +148,7 @@ class getid3_la extends getid3_handler
|
|
146 |
$offset += 4;
|
147 |
|
148 |
if ($info['la']['footerstart'] > $info['filesize']) {
|
149 |
-
$
|
150 |
$info['la']['footerstart'] = $info['filesize'];
|
151 |
}
|
152 |
|
@@ -182,7 +184,7 @@ class getid3_la extends getid3_handler
|
|
182 |
if (empty($getid3_temp->info['error'])) {
|
183 |
$info['riff'] = $getid3_temp->info['riff'];
|
184 |
} else {
|
185 |
-
$
|
186 |
}
|
187 |
unset($getid3_temp, $getid3_riff);
|
188 |
}
|
@@ -197,7 +199,7 @@ class getid3_la extends getid3_handler
|
|
197 |
$info['la']['compression_ratio'] = (float) (($info['avdataend'] - $info['avdataoffset']) / $info['la']['uncompressed_size']);
|
198 |
$info['playtime_seconds'] = (float) ($info['la']['samples'] / $info['la']['sample_rate']) / $info['la']['channels'];
|
199 |
if ($info['playtime_seconds'] == 0) {
|
200 |
-
$
|
201 |
return false;
|
202 |
}
|
203 |
|
@@ -208,9 +210,9 @@ class getid3_la extends getid3_handler
|
|
208 |
|
209 |
default:
|
210 |
if (substr($rawdata, $offset, 2) == 'LA') {
|
211 |
-
$
|
212 |
} else {
|
213 |
-
$
|
214 |
}
|
215 |
return false;
|
216 |
break;
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.la.php //
|
18 |
|
19 |
class getid3_la extends getid3_handler
|
20 |
{
|
21 |
+
/**
|
22 |
+
* @return bool
|
23 |
+
*/
|
24 |
public function Analyze() {
|
25 |
$info = &$this->getid3->info;
|
26 |
|
44 |
$info['la']['uncompressed_size'] = getid3_lib::LittleEndian2Int(substr($rawdata, $offset, 4));
|
45 |
$offset += 4;
|
46 |
if ($info['la']['uncompressed_size'] == 0) {
|
47 |
+
$this->error('Corrupt LA file: uncompressed_size == zero');
|
48 |
return false;
|
49 |
}
|
50 |
|
51 |
$WAVEchunk = substr($rawdata, $offset, 4);
|
52 |
if ($WAVEchunk !== 'WAVE') {
|
53 |
+
$this->error('Expected "WAVE" ('.getid3_lib::PrintHexBytes('WAVE').') at offset '.$offset.', found "'.$WAVEchunk.'" ('.getid3_lib::PrintHexBytes($WAVEchunk).') instead.');
|
54 |
return false;
|
55 |
}
|
56 |
$offset += 4;
|
71 |
|
72 |
$fmt_chunk = substr($rawdata, $offset, 4);
|
73 |
if ($fmt_chunk !== 'fmt ') {
|
74 |
+
$this->error('Expected "fmt " ('.getid3_lib::PrintHexBytes('fmt ').') at offset '.$offset.', found "'.$fmt_chunk.'" ('.getid3_lib::PrintHexBytes($fmt_chunk).') instead.');
|
75 |
return false;
|
76 |
}
|
77 |
$offset += 4;
|
84 |
$info['la']['channels'] = getid3_lib::LittleEndian2Int(substr($rawdata, $offset, 2));
|
85 |
$offset += 2;
|
86 |
if ($info['la']['channels'] == 0) {
|
87 |
+
$this->error('Corrupt LA file: channels == zero');
|
88 |
return false;
|
89 |
}
|
90 |
|
91 |
$info['la']['sample_rate'] = getid3_lib::LittleEndian2Int(substr($rawdata, $offset, 4));
|
92 |
$offset += 4;
|
93 |
if ($info['la']['sample_rate'] == 0) {
|
94 |
+
$this->error('Corrupt LA file: sample_rate == zero');
|
95 |
return false;
|
96 |
}
|
97 |
|
148 |
$offset += 4;
|
149 |
|
150 |
if ($info['la']['footerstart'] > $info['filesize']) {
|
151 |
+
$this->warning('FooterStart value points to offset '.$info['la']['footerstart'].' which is beyond end-of-file ('.$info['filesize'].')');
|
152 |
$info['la']['footerstart'] = $info['filesize'];
|
153 |
}
|
154 |
|
184 |
if (empty($getid3_temp->info['error'])) {
|
185 |
$info['riff'] = $getid3_temp->info['riff'];
|
186 |
} else {
|
187 |
+
$this->warning('Error parsing RIFF portion of La file: '.implode($getid3_temp->info['error']));
|
188 |
}
|
189 |
unset($getid3_temp, $getid3_riff);
|
190 |
}
|
199 |
$info['la']['compression_ratio'] = (float) (($info['avdataend'] - $info['avdataoffset']) / $info['la']['uncompressed_size']);
|
200 |
$info['playtime_seconds'] = (float) ($info['la']['samples'] / $info['la']['sample_rate']) / $info['la']['channels'];
|
201 |
if ($info['playtime_seconds'] == 0) {
|
202 |
+
$this->error('Corrupt LA file: playtime_seconds == zero');
|
203 |
return false;
|
204 |
}
|
205 |
|
210 |
|
211 |
default:
|
212 |
if (substr($rawdata, $offset, 2) == 'LA') {
|
213 |
+
$this->error('This version of getID3() ['.$this->getid3->version().'] does not support LA version '.substr($rawdata, $offset + 2, 1).'.'.substr($rawdata, $offset + 3, 1).' which this appears to be - check http://getid3.sourceforge.net for updates.');
|
214 |
} else {
|
215 |
+
$this->error('Not a LA (Lossless-Audio) file');
|
216 |
}
|
217 |
return false;
|
218 |
break;
|
lib/getid3/module.audio.lpac.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.lpac.php //
|
@@ -18,14 +18,17 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php',
|
|
18 |
|
19 |
class getid3_lpac extends getid3_handler
|
20 |
{
|
21 |
-
|
|
|
|
|
22 |
public function Analyze() {
|
23 |
$info = &$this->getid3->info;
|
24 |
|
25 |
$this->fseek($info['avdataoffset']);
|
26 |
$LPACheader = $this->fread(14);
|
27 |
-
|
28 |
-
|
|
|
29 |
return false;
|
30 |
}
|
31 |
$info['avdataoffset'] += 14;
|
@@ -46,7 +49,7 @@ class getid3_lpac extends getid3_handler
|
|
46 |
$info['lpac']['flags']['16_bit'] = (bool) ($flags['audio_type'] & 0x01);
|
47 |
|
48 |
if ($info['lpac']['flags']['24_bit'] && $info['lpac']['flags']['16_bit']) {
|
49 |
-
$
|
50 |
}
|
51 |
|
52 |
$info['lpac']['flags']['fast_compress'] = (bool) ($flags['parameters'] & 0x40000000);
|
@@ -59,20 +62,20 @@ class getid3_lpac extends getid3_handler
|
|
59 |
$info['lpac']['max_prediction_order'] = ($flags['parameters'] & 0x0000003F);
|
60 |
|
61 |
if ($info['lpac']['flags']['fast_compress'] && ($info['lpac']['max_prediction_order'] != 3)) {
|
62 |
-
$
|
63 |
}
|
64 |
switch ($info['lpac']['file_version']) {
|
65 |
case 6:
|
66 |
if ($info['lpac']['flags']['adaptive_quantization']) {
|
67 |
-
$
|
68 |
}
|
69 |
if ($info['lpac']['quantization'] != 20) {
|
70 |
-
$
|
71 |
}
|
72 |
break;
|
73 |
|
74 |
default:
|
75 |
-
//$
|
76 |
break;
|
77 |
}
|
78 |
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.lpac.php //
|
18 |
|
19 |
class getid3_lpac extends getid3_handler
|
20 |
{
|
21 |
+
/**
|
22 |
+
* @return bool
|
23 |
+
*/
|
24 |
public function Analyze() {
|
25 |
$info = &$this->getid3->info;
|
26 |
|
27 |
$this->fseek($info['avdataoffset']);
|
28 |
$LPACheader = $this->fread(14);
|
29 |
+
$StreamMarker = substr($LPACheader, 0, 4);
|
30 |
+
if ($StreamMarker != 'LPAC') {
|
31 |
+
$this->error('Expected "LPAC" at offset '.$info['avdataoffset'].', found "'.$StreamMarker.'"');
|
32 |
return false;
|
33 |
}
|
34 |
$info['avdataoffset'] += 14;
|
49 |
$info['lpac']['flags']['16_bit'] = (bool) ($flags['audio_type'] & 0x01);
|
50 |
|
51 |
if ($info['lpac']['flags']['24_bit'] && $info['lpac']['flags']['16_bit']) {
|
52 |
+
$this->warning('24-bit and 16-bit flags cannot both be set');
|
53 |
}
|
54 |
|
55 |
$info['lpac']['flags']['fast_compress'] = (bool) ($flags['parameters'] & 0x40000000);
|
62 |
$info['lpac']['max_prediction_order'] = ($flags['parameters'] & 0x0000003F);
|
63 |
|
64 |
if ($info['lpac']['flags']['fast_compress'] && ($info['lpac']['max_prediction_order'] != 3)) {
|
65 |
+
$this->warning('max_prediction_order expected to be "3" if fast_compress is true, actual value is "'.$info['lpac']['max_prediction_order'].'"');
|
66 |
}
|
67 |
switch ($info['lpac']['file_version']) {
|
68 |
case 6:
|
69 |
if ($info['lpac']['flags']['adaptive_quantization']) {
|
70 |
+
$this->warning('adaptive_quantization expected to be false in LPAC file stucture v6, actually true');
|
71 |
}
|
72 |
if ($info['lpac']['quantization'] != 20) {
|
73 |
+
$this->warning('Quantization expected to be 20 in LPAC file stucture v6, actually '.$info['lpac']['flags']['Q']);
|
74 |
}
|
75 |
break;
|
76 |
|
77 |
default:
|
78 |
+
//$this->warning('This version of getID3() ['.$this->getid3->version().'] only supports LPAC file format version 6, this file is version '.$info['lpac']['file_version'].' - please report to info@getid3.org');
|
79 |
break;
|
80 |
}
|
81 |
|
lib/getid3/module.audio.midi.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.midi.php //
|
@@ -19,8 +19,14 @@ define('GETID3_MIDI_MAGIC_MTRK', 'MTrk'); // MIDI track header magic
|
|
19 |
|
20 |
class getid3_midi extends getid3_handler
|
21 |
{
|
|
|
|
|
|
|
22 |
public $scanwholefile = true;
|
23 |
|
|
|
|
|
|
|
24 |
public function Analyze() {
|
25 |
$info = &$this->getid3->info;
|
26 |
|
@@ -37,7 +43,7 @@ class getid3_midi extends getid3_handler
|
|
37 |
$offset = 0;
|
38 |
$MIDIheaderID = substr($MIDIdata, $offset, 4); // 'MThd'
|
39 |
if ($MIDIheaderID != GETID3_MIDI_MAGIC_MTHD) {
|
40 |
-
$
|
41 |
unset($info['fileformat']);
|
42 |
return false;
|
43 |
}
|
@@ -56,8 +62,8 @@ class getid3_midi extends getid3_handler
|
|
56 |
if ($buffer = $this->fread($this->getid3->fread_buffer_size())) {
|
57 |
$MIDIdata .= $buffer;
|
58 |
} else {
|
59 |
-
$
|
60 |
-
$
|
61 |
return false;
|
62 |
}
|
63 |
}
|
@@ -70,13 +76,13 @@ class getid3_midi extends getid3_handler
|
|
70 |
$trackdataarray[$i] = substr($MIDIdata, $offset, $tracksize);
|
71 |
$offset += $tracksize;
|
72 |
} else {
|
73 |
-
$
|
74 |
return false;
|
75 |
}
|
76 |
}
|
77 |
|
78 |
if (!isset($trackdataarray) || !is_array($trackdataarray)) {
|
79 |
-
$
|
80 |
unset($thisfile_midi);
|
81 |
unset($info['fileformat']);
|
82 |
return false;
|
@@ -88,6 +94,7 @@ class getid3_midi extends getid3_handler
|
|
88 |
$CurrentMicroSecondsPerBeat = 500000; // 120 beats per minute; 60,000,000 microseconds per minute -> 500,000 microseconds per beat
|
89 |
$CurrentBeatsPerMinute = 120; // 120 beats per minute; 60,000,000 microseconds per minute -> 500,000 microseconds per beat
|
90 |
$MicroSecondsPerQuarterNoteAfter = array ();
|
|
|
91 |
|
92 |
foreach ($trackdataarray as $tracknumber => $trackdata) {
|
93 |
|
@@ -226,7 +233,7 @@ class getid3_midi extends getid3_handler
|
|
226 |
case 0x51: // Tempo: microseconds / quarter note
|
227 |
$CurrentMicroSecondsPerBeat = getid3_lib::BigEndian2Int(substr($METAeventData, 0, $METAeventLength));
|
228 |
if ($CurrentMicroSecondsPerBeat == 0) {
|
229 |
-
$
|
230 |
return false;
|
231 |
}
|
232 |
$thisfile_midi_raw['events'][$tracknumber][$CumulativeDeltaTime]['us_qnote'] = $CurrentMicroSecondsPerBeat;
|
@@ -269,13 +276,13 @@ class getid3_midi extends getid3_handler
|
|
269 |
break;
|
270 |
|
271 |
default:
|
272 |
-
$
|
273 |
break;
|
274 |
}
|
275 |
|
276 |
} else {
|
277 |
|
278 |
-
$
|
279 |
|
280 |
}
|
281 |
}
|
@@ -283,7 +290,8 @@ class getid3_midi extends getid3_handler
|
|
283 |
$thisfile_midi['totalticks'] = max($thisfile_midi['totalticks'], $CumulativeDeltaTime);
|
284 |
}
|
285 |
}
|
286 |
-
$previoustickoffset
|
|
|
287 |
|
288 |
ksort($MicroSecondsPerQuarterNoteAfter);
|
289 |
foreach ($MicroSecondsPerQuarterNoteAfter as $tickoffset => $microsecondsperbeat) {
|
@@ -295,7 +303,7 @@ class getid3_midi extends getid3_handler
|
|
295 |
if ($thisfile_midi['totalticks'] > $tickoffset) {
|
296 |
|
297 |
if ($thisfile_midi_raw['ticksperqnote'] == 0) {
|
298 |
-
$
|
299 |
return false;
|
300 |
}
|
301 |
|
@@ -308,11 +316,11 @@ class getid3_midi extends getid3_handler
|
|
308 |
if ($thisfile_midi['totalticks'] > $previoustickoffset) {
|
309 |
|
310 |
if ($thisfile_midi_raw['ticksperqnote'] == 0) {
|
311 |
-
$
|
312 |
return false;
|
313 |
}
|
314 |
|
315 |
-
$info['playtime_seconds'] += (($thisfile_midi['totalticks'] - $previoustickoffset) / $thisfile_midi_raw['ticksperqnote']) * ($
|
316 |
|
317 |
}
|
318 |
}
|
@@ -329,6 +337,11 @@ class getid3_midi extends getid3_handler
|
|
329 |
return true;
|
330 |
}
|
331 |
|
|
|
|
|
|
|
|
|
|
|
332 |
public function GeneralMIDIinstrumentLookup($instrumentid) {
|
333 |
|
334 |
$begin = __LINE__;
|
@@ -469,6 +482,11 @@ class getid3_midi extends getid3_handler
|
|
469 |
return getid3_lib::EmbeddedLookup($instrumentid, $begin, __LINE__, __FILE__, 'GeneralMIDIinstrument');
|
470 |
}
|
471 |
|
|
|
|
|
|
|
|
|
|
|
472 |
public function GeneralMIDIpercussionLookup($instrumentid) {
|
473 |
|
474 |
$begin = __LINE__;
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.midi.php //
|
19 |
|
20 |
class getid3_midi extends getid3_handler
|
21 |
{
|
22 |
+
/**
|
23 |
+
* @var bool
|
24 |
+
*/
|
25 |
public $scanwholefile = true;
|
26 |
|
27 |
+
/**
|
28 |
+
* @return bool
|
29 |
+
*/
|
30 |
public function Analyze() {
|
31 |
$info = &$this->getid3->info;
|
32 |
|
43 |
$offset = 0;
|
44 |
$MIDIheaderID = substr($MIDIdata, $offset, 4); // 'MThd'
|
45 |
if ($MIDIheaderID != GETID3_MIDI_MAGIC_MTHD) {
|
46 |
+
$this->error('Expecting "'.getid3_lib::PrintHexBytes(GETID3_MIDI_MAGIC_MTHD).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($MIDIheaderID).'"');
|
47 |
unset($info['fileformat']);
|
48 |
return false;
|
49 |
}
|
62 |
if ($buffer = $this->fread($this->getid3->fread_buffer_size())) {
|
63 |
$MIDIdata .= $buffer;
|
64 |
} else {
|
65 |
+
$this->warning('only processed '.($i - 1).' of '.$thisfile_midi_raw['tracks'].' tracks');
|
66 |
+
$this->error('Unabled to read more file data at '.$this->ftell().' (trying to seek to : '.$offset.'), was expecting at least 8 more bytes');
|
67 |
return false;
|
68 |
}
|
69 |
}
|
76 |
$trackdataarray[$i] = substr($MIDIdata, $offset, $tracksize);
|
77 |
$offset += $tracksize;
|
78 |
} else {
|
79 |
+
$this->error('Expecting "'.getid3_lib::PrintHexBytes(GETID3_MIDI_MAGIC_MTRK).'" at '.($offset - 4).', found "'.getid3_lib::PrintHexBytes($trackID).'" instead');
|
80 |
return false;
|
81 |
}
|
82 |
}
|
83 |
|
84 |
if (!isset($trackdataarray) || !is_array($trackdataarray)) {
|
85 |
+
$this->error('Cannot find MIDI track information');
|
86 |
unset($thisfile_midi);
|
87 |
unset($info['fileformat']);
|
88 |
return false;
|
94 |
$CurrentMicroSecondsPerBeat = 500000; // 120 beats per minute; 60,000,000 microseconds per minute -> 500,000 microseconds per beat
|
95 |
$CurrentBeatsPerMinute = 120; // 120 beats per minute; 60,000,000 microseconds per minute -> 500,000 microseconds per beat
|
96 |
$MicroSecondsPerQuarterNoteAfter = array ();
|
97 |
+
$MIDIevents = array();
|
98 |
|
99 |
foreach ($trackdataarray as $tracknumber => $trackdata) {
|
100 |
|
233 |
case 0x51: // Tempo: microseconds / quarter note
|
234 |
$CurrentMicroSecondsPerBeat = getid3_lib::BigEndian2Int(substr($METAeventData, 0, $METAeventLength));
|
235 |
if ($CurrentMicroSecondsPerBeat == 0) {
|
236 |
+
$this->error('Corrupt MIDI file: CurrentMicroSecondsPerBeat == zero');
|
237 |
return false;
|
238 |
}
|
239 |
$thisfile_midi_raw['events'][$tracknumber][$CumulativeDeltaTime]['us_qnote'] = $CurrentMicroSecondsPerBeat;
|
276 |
break;
|
277 |
|
278 |
default:
|
279 |
+
$this->warning('Unhandled META Event Command: '.$METAeventCommand);
|
280 |
break;
|
281 |
}
|
282 |
|
283 |
} else {
|
284 |
|
285 |
+
$this->warning('Unhandled MIDI Event ID: '.$MIDIevents[$tracknumber][$eventid]['eventid'].' + Channel ID: '.$MIDIevents[$tracknumber][$eventid]['channel']);
|
286 |
|
287 |
}
|
288 |
}
|
290 |
$thisfile_midi['totalticks'] = max($thisfile_midi['totalticks'], $CumulativeDeltaTime);
|
291 |
}
|
292 |
}
|
293 |
+
$previoustickoffset = null;
|
294 |
+
$prevmicrosecondsperbeat = null;
|
295 |
|
296 |
ksort($MicroSecondsPerQuarterNoteAfter);
|
297 |
foreach ($MicroSecondsPerQuarterNoteAfter as $tickoffset => $microsecondsperbeat) {
|
303 |
if ($thisfile_midi['totalticks'] > $tickoffset) {
|
304 |
|
305 |
if ($thisfile_midi_raw['ticksperqnote'] == 0) {
|
306 |
+
$this->error('Corrupt MIDI file: ticksperqnote == zero');
|
307 |
return false;
|
308 |
}
|
309 |
|
316 |
if ($thisfile_midi['totalticks'] > $previoustickoffset) {
|
317 |
|
318 |
if ($thisfile_midi_raw['ticksperqnote'] == 0) {
|
319 |
+
$this->error('Corrupt MIDI file: ticksperqnote == zero');
|
320 |
return false;
|
321 |
}
|
322 |
|
323 |
+
$info['playtime_seconds'] += (($thisfile_midi['totalticks'] - $previoustickoffset) / $thisfile_midi_raw['ticksperqnote']) * ($prevmicrosecondsperbeat / 1000000);
|
324 |
|
325 |
}
|
326 |
}
|
337 |
return true;
|
338 |
}
|
339 |
|
340 |
+
/**
|
341 |
+
* @param int $instrumentid
|
342 |
+
*
|
343 |
+
* @return string
|
344 |
+
*/
|
345 |
public function GeneralMIDIinstrumentLookup($instrumentid) {
|
346 |
|
347 |
$begin = __LINE__;
|
482 |
return getid3_lib::EmbeddedLookup($instrumentid, $begin, __LINE__, __FILE__, 'GeneralMIDIinstrument');
|
483 |
}
|
484 |
|
485 |
+
/**
|
486 |
+
* @param int $instrumentid
|
487 |
+
*
|
488 |
+
* @return string
|
489 |
+
*/
|
490 |
public function GeneralMIDIpercussionLookup($instrumentid) {
|
491 |
|
492 |
$begin = __LINE__;
|
lib/getid3/module.audio.mod.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.mod.php //
|
@@ -17,7 +17,9 @@
|
|
17 |
|
18 |
class getid3_mod extends getid3_handler
|
19 |
{
|
20 |
-
|
|
|
|
|
21 |
public function Analyze() {
|
22 |
$info = &$this->getid3->info;
|
23 |
$this->fseek($info['avdataoffset']);
|
@@ -31,68 +33,79 @@ class getid3_mod extends getid3_handler
|
|
31 |
} elseif (preg_match('#^.{1080}(M\\.K\\.|M!K!|FLT4|FLT8|[5-9]CHN|[1-3][0-9]CH)#', $fileheader)) {
|
32 |
return $this->getMODheaderFilepointer();
|
33 |
}
|
34 |
-
$
|
35 |
return false;
|
36 |
}
|
37 |
|
38 |
-
|
|
|
|
|
39 |
public function getMODheaderFilepointer() {
|
40 |
$info = &$this->getid3->info;
|
41 |
$this->fseek($info['avdataoffset'] + 1080);
|
42 |
$FormatID = $this->fread(4);
|
43 |
if (!preg_match('#^(M.K.|[5-9]CHN|[1-3][0-9]CH)$#', $FormatID)) {
|
44 |
-
$
|
45 |
return false;
|
46 |
}
|
47 |
|
48 |
$info['fileformat'] = 'mod';
|
49 |
|
50 |
-
$
|
51 |
return false;
|
52 |
}
|
53 |
|
|
|
|
|
|
|
54 |
public function getXMheaderFilepointer() {
|
55 |
$info = &$this->getid3->info;
|
56 |
$this->fseek($info['avdataoffset']);
|
57 |
$FormatID = $this->fread(15);
|
58 |
if (!preg_match('#^Extended Module$#', $FormatID)) {
|
59 |
-
$
|
60 |
return false;
|
61 |
}
|
62 |
|
63 |
$info['fileformat'] = 'xm';
|
64 |
|
65 |
-
$
|
66 |
return false;
|
67 |
}
|
68 |
|
|
|
|
|
|
|
69 |
public function getS3MheaderFilepointer() {
|
70 |
$info = &$this->getid3->info;
|
71 |
$this->fseek($info['avdataoffset'] + 44);
|
72 |
$FormatID = $this->fread(4);
|
73 |
if (!preg_match('#^SCRM$#', $FormatID)) {
|
74 |
-
$
|
75 |
return false;
|
76 |
}
|
77 |
|
78 |
$info['fileformat'] = 's3m';
|
79 |
|
80 |
-
$
|
81 |
return false;
|
82 |
}
|
83 |
|
|
|
|
|
|
|
84 |
public function getITheaderFilepointer() {
|
85 |
$info = &$this->getid3->info;
|
86 |
$this->fseek($info['avdataoffset']);
|
87 |
$FormatID = $this->fread(4);
|
88 |
if (!preg_match('#^IMPM$#', $FormatID)) {
|
89 |
-
$
|
90 |
return false;
|
91 |
}
|
92 |
|
93 |
$info['fileformat'] = 'it';
|
94 |
|
95 |
-
$
|
96 |
return false;
|
97 |
}
|
98 |
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.mod.php //
|
17 |
|
18 |
class getid3_mod extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @return bool
|
22 |
+
*/
|
23 |
public function Analyze() {
|
24 |
$info = &$this->getid3->info;
|
25 |
$this->fseek($info['avdataoffset']);
|
33 |
} elseif (preg_match('#^.{1080}(M\\.K\\.|M!K!|FLT4|FLT8|[5-9]CHN|[1-3][0-9]CH)#', $fileheader)) {
|
34 |
return $this->getMODheaderFilepointer();
|
35 |
}
|
36 |
+
$this->error('This is not a known type of MOD file');
|
37 |
return false;
|
38 |
}
|
39 |
|
40 |
+
/**
|
41 |
+
* @return bool
|
42 |
+
*/
|
43 |
public function getMODheaderFilepointer() {
|
44 |
$info = &$this->getid3->info;
|
45 |
$this->fseek($info['avdataoffset'] + 1080);
|
46 |
$FormatID = $this->fread(4);
|
47 |
if (!preg_match('#^(M.K.|[5-9]CHN|[1-3][0-9]CH)$#', $FormatID)) {
|
48 |
+
$this->error('This is not a known type of MOD file');
|
49 |
return false;
|
50 |
}
|
51 |
|
52 |
$info['fileformat'] = 'mod';
|
53 |
|
54 |
+
$this->error('MOD parsing not enabled in this version of getID3() ['.$this->getid3->version().']');
|
55 |
return false;
|
56 |
}
|
57 |
|
58 |
+
/**
|
59 |
+
* @return bool
|
60 |
+
*/
|
61 |
public function getXMheaderFilepointer() {
|
62 |
$info = &$this->getid3->info;
|
63 |
$this->fseek($info['avdataoffset']);
|
64 |
$FormatID = $this->fread(15);
|
65 |
if (!preg_match('#^Extended Module$#', $FormatID)) {
|
66 |
+
$this->error('This is not a known type of XM-MOD file');
|
67 |
return false;
|
68 |
}
|
69 |
|
70 |
$info['fileformat'] = 'xm';
|
71 |
|
72 |
+
$this->error('XM-MOD parsing not enabled in this version of getID3() ['.$this->getid3->version().']');
|
73 |
return false;
|
74 |
}
|
75 |
|
76 |
+
/**
|
77 |
+
* @return bool
|
78 |
+
*/
|
79 |
public function getS3MheaderFilepointer() {
|
80 |
$info = &$this->getid3->info;
|
81 |
$this->fseek($info['avdataoffset'] + 44);
|
82 |
$FormatID = $this->fread(4);
|
83 |
if (!preg_match('#^SCRM$#', $FormatID)) {
|
84 |
+
$this->error('This is not a ScreamTracker MOD file');
|
85 |
return false;
|
86 |
}
|
87 |
|
88 |
$info['fileformat'] = 's3m';
|
89 |
|
90 |
+
$this->error('ScreamTracker parsing not enabled in this version of getID3() ['.$this->getid3->version().']');
|
91 |
return false;
|
92 |
}
|
93 |
|
94 |
+
/**
|
95 |
+
* @return bool
|
96 |
+
*/
|
97 |
public function getITheaderFilepointer() {
|
98 |
$info = &$this->getid3->info;
|
99 |
$this->fseek($info['avdataoffset']);
|
100 |
$FormatID = $this->fread(4);
|
101 |
if (!preg_match('#^IMPM$#', $FormatID)) {
|
102 |
+
$this->error('This is not an ImpulseTracker MOD file');
|
103 |
return false;
|
104 |
}
|
105 |
|
106 |
$info['fileformat'] = 'it';
|
107 |
|
108 |
+
$this->error('ImpulseTracker parsing not enabled in this version of getID3() ['.$this->getid3->version().']');
|
109 |
return false;
|
110 |
}
|
111 |
|
lib/getid3/module.audio.monkey.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.monkey.php //
|
@@ -17,7 +17,9 @@
|
|
17 |
|
18 |
class getid3_monkey extends getid3_handler
|
19 |
{
|
20 |
-
|
|
|
|
|
21 |
public function Analyze() {
|
22 |
$info = &$this->getid3->info;
|
23 |
|
@@ -39,7 +41,7 @@ class getid3_monkey extends getid3_handler
|
|
39 |
$thisfile_monkeysaudio_raw['magic'] = substr($MACheaderData, 0, 4);
|
40 |
$magic = 'MAC ';
|
41 |
if ($thisfile_monkeysaudio_raw['magic'] != $magic) {
|
42 |
-
$
|
43 |
unset($info['fileformat']);
|
44 |
return false;
|
45 |
}
|
@@ -112,7 +114,7 @@ class getid3_monkey extends getid3_handler
|
|
112 |
$info['audio']['channels'] = $thisfile_monkeysaudio['channels'];
|
113 |
$thisfile_monkeysaudio['sample_rate'] = $thisfile_monkeysaudio_raw['nSampleRate'];
|
114 |
if ($thisfile_monkeysaudio['sample_rate'] == 0) {
|
115 |
-
$
|
116 |
return false;
|
117 |
}
|
118 |
$info['audio']['sample_rate'] = $thisfile_monkeysaudio['sample_rate'];
|
@@ -127,14 +129,14 @@ class getid3_monkey extends getid3_handler
|
|
127 |
}
|
128 |
$thisfile_monkeysaudio['playtime'] = $thisfile_monkeysaudio['samples'] / $thisfile_monkeysaudio['sample_rate'];
|
129 |
if ($thisfile_monkeysaudio['playtime'] == 0) {
|
130 |
-
$
|
131 |
return false;
|
132 |
}
|
133 |
$info['playtime_seconds'] = $thisfile_monkeysaudio['playtime'];
|
134 |
$thisfile_monkeysaudio['compressed_size'] = $info['avdataend'] - $info['avdataoffset'];
|
135 |
$thisfile_monkeysaudio['uncompressed_size'] = $thisfile_monkeysaudio['samples'] * $thisfile_monkeysaudio['channels'] * ($thisfile_monkeysaudio['bits_per_sample'] / 8);
|
136 |
if ($thisfile_monkeysaudio['uncompressed_size'] == 0) {
|
137 |
-
$
|
138 |
return false;
|
139 |
}
|
140 |
$thisfile_monkeysaudio['compression_ratio'] = $thisfile_monkeysaudio['compressed_size'] / ($thisfile_monkeysaudio['uncompressed_size'] + $thisfile_monkeysaudio_raw['nHeaderDataBytes']);
|
@@ -155,7 +157,7 @@ class getid3_monkey extends getid3_handler
|
|
155 |
|
156 |
if ($thisfile_monkeysaudio_raw['nVersion'] >= 3980) {
|
157 |
if ($thisfile_monkeysaudio_raw['cFileMD5'] === str_repeat("\x00", 16)) {
|
158 |
-
//$
|
159 |
} else {
|
160 |
$info['md5_data_source'] = '';
|
161 |
$md5 = $thisfile_monkeysaudio_raw['cFileMD5'];
|
@@ -177,6 +179,11 @@ class getid3_monkey extends getid3_handler
|
|
177 |
return true;
|
178 |
}
|
179 |
|
|
|
|
|
|
|
|
|
|
|
180 |
public function MonkeyCompressionLevelNameLookup($compressionlevel) {
|
181 |
static $MonkeyCompressionLevelNameLookup = array(
|
182 |
0 => 'unknown',
|
@@ -189,6 +196,12 @@ class getid3_monkey extends getid3_handler
|
|
189 |
return (isset($MonkeyCompressionLevelNameLookup[$compressionlevel]) ? $MonkeyCompressionLevelNameLookup[$compressionlevel] : 'invalid');
|
190 |
}
|
191 |
|
|
|
|
|
|
|
|
|
|
|
|
|
192 |
public function MonkeySamplesPerFrame($versionid, $compressionlevel) {
|
193 |
if ($versionid >= 3950) {
|
194 |
return 73728 * 4;
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.monkey.php //
|
17 |
|
18 |
class getid3_monkey extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @return bool
|
22 |
+
*/
|
23 |
public function Analyze() {
|
24 |
$info = &$this->getid3->info;
|
25 |
|
41 |
$thisfile_monkeysaudio_raw['magic'] = substr($MACheaderData, 0, 4);
|
42 |
$magic = 'MAC ';
|
43 |
if ($thisfile_monkeysaudio_raw['magic'] != $magic) {
|
44 |
+
$this->error('Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($thisfile_monkeysaudio_raw['magic']).'"');
|
45 |
unset($info['fileformat']);
|
46 |
return false;
|
47 |
}
|
114 |
$info['audio']['channels'] = $thisfile_monkeysaudio['channels'];
|
115 |
$thisfile_monkeysaudio['sample_rate'] = $thisfile_monkeysaudio_raw['nSampleRate'];
|
116 |
if ($thisfile_monkeysaudio['sample_rate'] == 0) {
|
117 |
+
$this->error('Corrupt MAC file: frequency == zero');
|
118 |
return false;
|
119 |
}
|
120 |
$info['audio']['sample_rate'] = $thisfile_monkeysaudio['sample_rate'];
|
129 |
}
|
130 |
$thisfile_monkeysaudio['playtime'] = $thisfile_monkeysaudio['samples'] / $thisfile_monkeysaudio['sample_rate'];
|
131 |
if ($thisfile_monkeysaudio['playtime'] == 0) {
|
132 |
+
$this->error('Corrupt MAC file: playtime == zero');
|
133 |
return false;
|
134 |
}
|
135 |
$info['playtime_seconds'] = $thisfile_monkeysaudio['playtime'];
|
136 |
$thisfile_monkeysaudio['compressed_size'] = $info['avdataend'] - $info['avdataoffset'];
|
137 |
$thisfile_monkeysaudio['uncompressed_size'] = $thisfile_monkeysaudio['samples'] * $thisfile_monkeysaudio['channels'] * ($thisfile_monkeysaudio['bits_per_sample'] / 8);
|
138 |
if ($thisfile_monkeysaudio['uncompressed_size'] == 0) {
|
139 |
+
$this->error('Corrupt MAC file: uncompressed_size == zero');
|
140 |
return false;
|
141 |
}
|
142 |
$thisfile_monkeysaudio['compression_ratio'] = $thisfile_monkeysaudio['compressed_size'] / ($thisfile_monkeysaudio['uncompressed_size'] + $thisfile_monkeysaudio_raw['nHeaderDataBytes']);
|
157 |
|
158 |
if ($thisfile_monkeysaudio_raw['nVersion'] >= 3980) {
|
159 |
if ($thisfile_monkeysaudio_raw['cFileMD5'] === str_repeat("\x00", 16)) {
|
160 |
+
//$this->warning('cFileMD5 is null');
|
161 |
} else {
|
162 |
$info['md5_data_source'] = '';
|
163 |
$md5 = $thisfile_monkeysaudio_raw['cFileMD5'];
|
179 |
return true;
|
180 |
}
|
181 |
|
182 |
+
/**
|
183 |
+
* @param int $compressionlevel
|
184 |
+
*
|
185 |
+
* @return string
|
186 |
+
*/
|
187 |
public function MonkeyCompressionLevelNameLookup($compressionlevel) {
|
188 |
static $MonkeyCompressionLevelNameLookup = array(
|
189 |
0 => 'unknown',
|
196 |
return (isset($MonkeyCompressionLevelNameLookup[$compressionlevel]) ? $MonkeyCompressionLevelNameLookup[$compressionlevel] : 'invalid');
|
197 |
}
|
198 |
|
199 |
+
/**
|
200 |
+
* @param int $versionid
|
201 |
+
* @param int $compressionlevel
|
202 |
+
*
|
203 |
+
* @return int
|
204 |
+
*/
|
205 |
public function MonkeySamplesPerFrame($versionid, $compressionlevel) {
|
206 |
if ($versionid >= 3950) {
|
207 |
return 73728 * 4;
|
lib/getid3/module.audio.mp3.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.mp3.php //
|
@@ -24,9 +24,17 @@ define('GETID3_MP3_VALID_CHECK_FRAMES', 35);
|
|
24 |
|
25 |
class getid3_mp3 extends getid3_handler
|
26 |
{
|
27 |
-
|
28 |
-
|
29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
public function Analyze() {
|
31 |
$info = &$this->getid3->info;
|
32 |
|
@@ -34,8 +42,8 @@ class getid3_mp3 extends getid3_handler
|
|
34 |
|
35 |
if (!$this->getOnlyMPEGaudioInfo($info['avdataoffset'])) {
|
36 |
if ($this->allow_bruteforce) {
|
37 |
-
$
|
38 |
-
$this->getOnlyMPEGaudioInfoBruteForce(
|
39 |
}
|
40 |
}
|
41 |
|
@@ -72,7 +80,7 @@ class getid3_mp3 extends getid3_handler
|
|
72 |
}
|
73 |
|
74 |
}
|
75 |
-
$
|
76 |
|
77 |
}
|
78 |
|
@@ -134,7 +142,7 @@ class getid3_mp3 extends getid3_handler
|
|
134 |
break;
|
135 |
|
136 |
default:
|
137 |
-
$
|
138 |
break;
|
139 |
}
|
140 |
}
|
@@ -152,7 +160,11 @@ class getid3_mp3 extends getid3_handler
|
|
152 |
|
153 |
// Calculate playtime
|
154 |
if (!isset($info['playtime_seconds']) && isset($info['audio']['bitrate']) && ($info['audio']['bitrate'] > 0)) {
|
155 |
-
|
|
|
|
|
|
|
|
|
156 |
}
|
157 |
|
158 |
$info['audio']['encoder_options'] = $this->GuessEncoderOptions();
|
@@ -160,10 +172,14 @@ class getid3_mp3 extends getid3_handler
|
|
160 |
return true;
|
161 |
}
|
162 |
|
163 |
-
|
|
|
|
|
164 |
public function GuessEncoderOptions() {
|
165 |
// shortcuts
|
166 |
$info = &$this->getid3->info;
|
|
|
|
|
167 |
if (!empty($info['mpeg']['audio'])) {
|
168 |
$thisfile_mpeg_audio = &$info['mpeg']['audio'];
|
169 |
if (!empty($thisfile_mpeg_audio['LAME'])) {
|
@@ -178,7 +194,7 @@ class getid3_mp3 extends getid3_handler
|
|
178 |
|
179 |
$encoder_options = 'VBR q'.$thisfile_mpeg_audio['VBR_quality'];
|
180 |
|
181 |
-
} elseif (!empty($thisfile_mpeg_audio_lame['preset_used']) && (!in_array($thisfile_mpeg_audio_lame['preset_used_id'], $NamedPresetBitrates))) {
|
182 |
|
183 |
$encoder_options = $thisfile_mpeg_audio_lame['preset_used'];
|
184 |
|
@@ -404,7 +420,15 @@ class getid3_mp3 extends getid3_handler
|
|
404 |
return $encoder_options;
|
405 |
}
|
406 |
|
407 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
408 |
public function decodeMPEGaudioHeader($offset, &$info, $recursivesearch=true, $ScanAsCBR=false, $FastMPEGheaderScan=false) {
|
409 |
static $MPEGaudioVersionLookup;
|
410 |
static $MPEGaudioLayerLookup;
|
@@ -424,7 +448,7 @@ class getid3_mp3 extends getid3_handler
|
|
424 |
}
|
425 |
|
426 |
if ($this->fseek($offset) != 0) {
|
427 |
-
$
|
428 |
return false;
|
429 |
}
|
430 |
//$headerstring = $this->fread(1441); // worst-case max length = 32kHz @ 320kbps layer 3 = 1441 bytes/frame
|
@@ -437,18 +461,19 @@ class getid3_mp3 extends getid3_handler
|
|
437 |
// and $cc... is the audio data
|
438 |
|
439 |
$head4 = substr($headerstring, 0, 4);
|
|
|
440 |
static $MPEGaudioHeaderDecodeCache = array();
|
441 |
-
if (isset($MPEGaudioHeaderDecodeCache[$
|
442 |
-
$MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$
|
443 |
} else {
|
444 |
$MPEGheaderRawArray = self::MPEGaudioHeaderDecode($head4);
|
445 |
-
$MPEGaudioHeaderDecodeCache[$
|
446 |
}
|
447 |
|
448 |
static $MPEGaudioHeaderValidCache = array();
|
449 |
-
if (!isset($MPEGaudioHeaderValidCache[$
|
450 |
-
//$MPEGaudioHeaderValidCache[$
|
451 |
-
$MPEGaudioHeaderValidCache[$
|
452 |
}
|
453 |
|
454 |
// shortcut
|
@@ -457,11 +482,10 @@ class getid3_mp3 extends getid3_handler
|
|
457 |
}
|
458 |
$thisfile_mpeg_audio = &$info['mpeg']['audio'];
|
459 |
|
460 |
-
|
461 |
-
if ($MPEGaudioHeaderValidCache[$head4]) {
|
462 |
$thisfile_mpeg_audio['raw'] = $MPEGheaderRawArray;
|
463 |
} else {
|
464 |
-
$
|
465 |
return false;
|
466 |
}
|
467 |
|
@@ -489,7 +513,7 @@ class getid3_mp3 extends getid3_handler
|
|
489 |
|
490 |
if ($thisfile_mpeg_audio['raw']['bitrate'] == 15) {
|
491 |
// http://www.hydrogenaudio.org/?act=ST&f=16&t=9682&st=0
|
492 |
-
$
|
493 |
$thisfile_mpeg_audio['raw']['bitrate'] = 0;
|
494 |
}
|
495 |
$thisfile_mpeg_audio['padding'] = (bool) $thisfile_mpeg_audio['raw']['padding'];
|
@@ -511,7 +535,7 @@ class getid3_mp3 extends getid3_handler
|
|
511 |
if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] <= 192000)) {
|
512 |
// these are ok
|
513 |
} else {
|
514 |
-
$
|
515 |
return false;
|
516 |
}
|
517 |
break;
|
@@ -522,7 +546,7 @@ class getid3_mp3 extends getid3_handler
|
|
522 |
if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] == 64000) || ($thisfile_mpeg_audio['bitrate'] >= 96000)) {
|
523 |
// these are ok
|
524 |
} else {
|
525 |
-
$
|
526 |
return false;
|
527 |
}
|
528 |
break;
|
@@ -544,7 +568,7 @@ class getid3_mp3 extends getid3_handler
|
|
544 |
if (isset($thisfile_mpeg_audio['framelength'])) {
|
545 |
$nextframetestoffset = $offset + $thisfile_mpeg_audio['framelength'];
|
546 |
} else {
|
547 |
-
$
|
548 |
return false;
|
549 |
}
|
550 |
|
@@ -561,7 +585,7 @@ class getid3_mp3 extends getid3_handler
|
|
561 |
|
562 |
$thisfile_mpeg_audio['bitrate_mode'] = 'vbr';
|
563 |
$thisfile_mpeg_audio['VBR_method'] = 'Fraunhofer';
|
564 |
-
$info['audio']['codec']
|
565 |
|
566 |
$SideInfoData = substr($headerstring, 4 + 2, 32);
|
567 |
|
@@ -654,10 +678,10 @@ class getid3_mp3 extends getid3_handler
|
|
654 |
$used_filesize = $thisfile_mpeg_audio['VBR_bytes'];
|
655 |
} elseif (!empty($info['filesize'])) {
|
656 |
$used_filesize = $info['filesize'];
|
657 |
-
$used_filesize -= intval(
|
658 |
$used_filesize -= (isset($info['id3v1']) ? 128 : 0);
|
659 |
$used_filesize -= (isset($info['tag_offset_end']) ? $info['tag_offset_end'] - $info['tag_offset_start'] : 0);
|
660 |
-
$
|
661 |
}
|
662 |
|
663 |
$framelengthfloat = $used_filesize / $thisfile_mpeg_audio['VBR_frames'];
|
@@ -847,7 +871,7 @@ class getid3_mp3 extends getid3_handler
|
|
847 |
$thisfile_mpeg_audio_lame['preset_used_id'] = ($PresetSurroundBytes & 0x07FF);
|
848 |
$thisfile_mpeg_audio_lame['preset_used'] = self::LAMEpresetUsedLookup($thisfile_mpeg_audio_lame);
|
849 |
if (!empty($thisfile_mpeg_audio_lame['preset_used_id']) && empty($thisfile_mpeg_audio_lame['preset_used'])) {
|
850 |
-
$
|
851 |
}
|
852 |
if (($thisfile_mpeg_audio_lame['short_version'] == 'LAME3.90.') && !empty($thisfile_mpeg_audio_lame['preset_used_id'])) {
|
853 |
// this may change if 3.90.4 ever comes out
|
@@ -891,7 +915,7 @@ class getid3_mp3 extends getid3_handler
|
|
891 |
$thisfile_mpeg_audio['bitrate_mode'] = 'cbr';
|
892 |
}
|
893 |
if ($thisfile_mpeg_audio['bitrate_mode'] == 'vbr') {
|
894 |
-
$
|
895 |
}
|
896 |
}
|
897 |
|
@@ -918,12 +942,12 @@ class getid3_mp3 extends getid3_handler
|
|
918 |
// $this->fseek($prenullbytefileoffset);
|
919 |
// if ($PossibleNullByte === "\x00") {
|
920 |
$info['avdataend']--;
|
921 |
-
// $
|
922 |
// } else {
|
923 |
-
// $
|
924 |
// }
|
925 |
} else {
|
926 |
-
$
|
927 |
}
|
928 |
}
|
929 |
}
|
@@ -941,7 +965,7 @@ class getid3_mp3 extends getid3_handler
|
|
941 |
$info['audio']['bitrate'] = (($framebytelength - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 144;
|
942 |
}
|
943 |
} else {
|
944 |
-
$
|
945 |
}
|
946 |
}
|
947 |
}
|
@@ -1082,9 +1106,16 @@ class getid3_mp3 extends getid3_handler
|
|
1082 |
return true;
|
1083 |
}
|
1084 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1085 |
public function RecursiveFrameScanning(&$offset, &$nextframetestoffset, $ScanAsCBR) {
|
1086 |
$info = &$this->getid3->info;
|
1087 |
-
$firstframetestarray = array('error'=>
|
1088 |
$this->decodeMPEGaudioHeader($offset, $firstframetestarray, false);
|
1089 |
|
1090 |
for ($i = 0; $i < GETID3_MP3_VALID_CHECK_FRAMES; $i++) {
|
@@ -1094,7 +1125,7 @@ class getid3_mp3 extends getid3_handler
|
|
1094 |
return true;
|
1095 |
}
|
1096 |
|
1097 |
-
$nextframetestarray = array('error'=>
|
1098 |
if ($this->decodeMPEGaudioHeader($nextframetestoffset, $nextframetestarray, false)) {
|
1099 |
if ($ScanAsCBR) {
|
1100 |
// force CBR mode, used for trying to pick out invalid audio streams with valid(?) VBR headers, or VBR streams with no VBR header
|
@@ -1108,7 +1139,7 @@ class getid3_mp3 extends getid3_handler
|
|
1108 |
if (isset($nextframetestarray['mpeg']['audio']['framelength']) && ($nextframetestarray['mpeg']['audio']['framelength'] > 0)) {
|
1109 |
$nextframetestoffset += $nextframetestarray['mpeg']['audio']['framelength'];
|
1110 |
} else {
|
1111 |
-
$
|
1112 |
return false;
|
1113 |
}
|
1114 |
|
@@ -1120,7 +1151,7 @@ class getid3_mp3 extends getid3_handler
|
|
1120 |
} else {
|
1121 |
|
1122 |
// next frame is not valid, note the error and fail, so scanning can contiue for a valid frame sequence
|
1123 |
-
$
|
1124 |
|
1125 |
return false;
|
1126 |
}
|
@@ -1128,6 +1159,12 @@ class getid3_mp3 extends getid3_handler
|
|
1128 |
return true;
|
1129 |
}
|
1130 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1131 |
public function FreeFormatFrameLength($offset, $deepscan=false) {
|
1132 |
$info = &$this->getid3->info;
|
1133 |
|
@@ -1163,10 +1200,10 @@ class getid3_mp3 extends getid3_handler
|
|
1163 |
$framelength = $framelength2;
|
1164 |
}
|
1165 |
if (!$framelength) {
|
1166 |
-
$
|
1167 |
return false;
|
1168 |
} else {
|
1169 |
-
$
|
1170 |
$info['audio']['codec'] = 'LAME';
|
1171 |
$info['audio']['encoder'] = 'LAME3.88';
|
1172 |
$SyncPattern1 = substr($SyncPattern1, 0, 3);
|
@@ -1193,7 +1230,7 @@ class getid3_mp3 extends getid3_handler
|
|
1193 |
$ActualFrameLengthValues[] = ($framelength + 1);
|
1194 |
$nextoffset++;
|
1195 |
} else {
|
1196 |
-
$
|
1197 |
return false;
|
1198 |
}
|
1199 |
$nextoffset += $framelength;
|
@@ -1205,6 +1242,9 @@ class getid3_mp3 extends getid3_handler
|
|
1205 |
return $framelength;
|
1206 |
}
|
1207 |
|
|
|
|
|
|
|
1208 |
public function getOnlyMPEGaudioInfoBruteForce() {
|
1209 |
$MPEGaudioHeaderDecodeCache = array();
|
1210 |
$MPEGaudioHeaderValidCache = array();
|
@@ -1291,7 +1331,7 @@ class getid3_mp3 extends getid3_handler
|
|
1291 |
getid3_lib::safe_inc($Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]]);
|
1292 |
if ($max_frames_scan && (++$frames_scanned >= $max_frames_scan)) {
|
1293 |
$pct_data_scanned = ($this->ftell() - $info['avdataoffset']) / ($info['avdataend'] - $info['avdataoffset']);
|
1294 |
-
$
|
1295 |
foreach ($Distribution as $key1 => $value1) {
|
1296 |
foreach ($value1 as $key2 => $value2) {
|
1297 |
$Distribution[$key1][$key2] = round($value2 / $pct_data_scanned);
|
@@ -1318,13 +1358,13 @@ class getid3_mp3 extends getid3_handler
|
|
1318 |
$info['mpeg']['audio']['version_distribution'] = $Distribution['version'];
|
1319 |
$info['mpeg']['audio']['padding_distribution'] = $Distribution['padding'];
|
1320 |
if (count($Distribution['version']) > 1) {
|
1321 |
-
$
|
1322 |
}
|
1323 |
if (count($Distribution['layer']) > 1) {
|
1324 |
-
$
|
1325 |
}
|
1326 |
if (count($Distribution['frequency']) > 1) {
|
1327 |
-
$
|
1328 |
}
|
1329 |
|
1330 |
|
@@ -1336,7 +1376,7 @@ class getid3_mp3 extends getid3_handler
|
|
1336 |
}
|
1337 |
$info['mpeg']['audio']['frame_count'] = array_sum($Distribution['bitrate']);
|
1338 |
if ($info['mpeg']['audio']['frame_count'] == 0) {
|
1339 |
-
$
|
1340 |
return false;
|
1341 |
}
|
1342 |
$info['mpeg']['audio']['bitrate'] = ($bittotal / $info['mpeg']['audio']['frame_count']);
|
@@ -1352,7 +1392,12 @@ class getid3_mp3 extends getid3_handler
|
|
1352 |
return true;
|
1353 |
}
|
1354 |
|
1355 |
-
|
|
|
|
|
|
|
|
|
|
|
1356 |
public function getOnlyMPEGaudioInfo($avdataoffset, $BitrateHistogram=false) {
|
1357 |
// looks for synch, decodes MPEG audio header
|
1358 |
|
@@ -1362,16 +1407,15 @@ class getid3_mp3 extends getid3_handler
|
|
1362 |
static $MPEGaudioLayerLookup;
|
1363 |
static $MPEGaudioBitrateLookup;
|
1364 |
if (empty($MPEGaudioVersionLookup)) {
|
1365 |
-
|
1366 |
-
|
1367 |
-
|
1368 |
-
|
1369 |
}
|
1370 |
|
1371 |
$this->fseek($avdataoffset);
|
1372 |
$sync_seek_buffer_size = min(128 * 1024, $info['avdataend'] - $avdataoffset);
|
1373 |
if ($sync_seek_buffer_size <= 0) {
|
1374 |
-
$
|
1375 |
return false;
|
1376 |
}
|
1377 |
$header = $this->fread($sync_seek_buffer_size);
|
@@ -1382,7 +1426,7 @@ class getid3_mp3 extends getid3_handler
|
|
1382 |
|
1383 |
if ($SynchSeekOffset > $sync_seek_buffer_size) {
|
1384 |
// if a synch's not found within the first 128k bytes, then give up
|
1385 |
-
$
|
1386 |
if (isset($info['audio']['bitrate'])) {
|
1387 |
unset($info['audio']['bitrate']);
|
1388 |
}
|
@@ -1396,7 +1440,7 @@ class getid3_mp3 extends getid3_handler
|
|
1396 |
|
1397 |
} elseif (feof($this->getid3->fp)) {
|
1398 |
|
1399 |
-
$
|
1400 |
if (isset($info['audio']['bitrate'])) {
|
1401 |
unset($info['audio']['bitrate']);
|
1402 |
}
|
@@ -1411,11 +1455,12 @@ class getid3_mp3 extends getid3_handler
|
|
1411 |
}
|
1412 |
|
1413 |
if (($SynchSeekOffset + 1) >= strlen($header)) {
|
1414 |
-
$
|
1415 |
return false;
|
1416 |
}
|
1417 |
|
1418 |
if (($header{$SynchSeekOffset} == "\xFF") && ($header{($SynchSeekOffset + 1)} > "\xE0")) { // synch detected
|
|
|
1419 |
if (!isset($FirstFrameThisfileInfo) && !isset($info['mpeg']['audio'])) {
|
1420 |
$FirstFrameThisfileInfo = $info;
|
1421 |
$FirstFrameAVDataOffset = $avdataoffset + $SynchSeekOffset;
|
@@ -1439,7 +1484,7 @@ class getid3_mp3 extends getid3_handler
|
|
1439 |
$info['audio']['dataformat'] = 'mp3';
|
1440 |
break;
|
1441 |
}
|
1442 |
-
if (isset($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode']) && ($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode'] == 'vbr')) {
|
1443 |
if (!(abs($info['audio']['bitrate'] - $FirstFrameThisfileInfo['audio']['bitrate']) <= 1)) {
|
1444 |
// If there is garbage data between a valid VBR header frame and a sequence
|
1445 |
// of valid MPEG-audio frames the VBR data is no longer discarded.
|
@@ -1454,9 +1499,9 @@ class getid3_mp3 extends getid3_handler
|
|
1454 |
if ($this->decodeMPEGaudioHeader($GarbageOffsetEnd, $dummy, true, true)) {
|
1455 |
$info = $dummy;
|
1456 |
$info['avdataoffset'] = $GarbageOffsetEnd;
|
1457 |
-
$
|
1458 |
} else {
|
1459 |
-
$
|
1460 |
}
|
1461 |
}
|
1462 |
}
|
@@ -1521,7 +1566,7 @@ class getid3_mp3 extends getid3_handler
|
|
1521 |
}
|
1522 |
}
|
1523 |
$synchstartoffset = $scan_start_offset[$current_segment];
|
1524 |
-
while ($this->decodeMPEGaudioHeader($synchstartoffset, $dummy, false, false, $FastMode)) {
|
1525 |
$FastMode = true;
|
1526 |
$thisframebitrate = $MPEGaudioBitrateLookup[$MPEGaudioVersionLookup[$dummy['mpeg']['audio']['raw']['version']]][$MPEGaudioLayerLookup[$dummy['mpeg']['audio']['raw']['layer']]][$dummy['mpeg']['audio']['raw']['bitrate']];
|
1527 |
|
@@ -1549,7 +1594,7 @@ class getid3_mp3 extends getid3_handler
|
|
1549 |
}
|
1550 |
}
|
1551 |
if ($pct_data_scanned > 0) {
|
1552 |
-
$
|
1553 |
foreach ($info['mpeg']['audio'] as $key1 => $value1) {
|
1554 |
if (!preg_match('#_distribution$#i', $key1)) {
|
1555 |
continue;
|
@@ -1561,7 +1606,7 @@ class getid3_mp3 extends getid3_handler
|
|
1561 |
}
|
1562 |
|
1563 |
if ($SynchErrorsFound > 0) {
|
1564 |
-
$
|
1565 |
//return false;
|
1566 |
}
|
1567 |
|
@@ -1574,7 +1619,7 @@ class getid3_mp3 extends getid3_handler
|
|
1574 |
}
|
1575 |
}
|
1576 |
if ($framecounter == 0) {
|
1577 |
-
$
|
1578 |
return false;
|
1579 |
}
|
1580 |
$info['mpeg']['audio']['frame_count'] = getid3_lib::CastAsInt($framecounter);
|
@@ -1609,7 +1654,7 @@ class getid3_mp3 extends getid3_handler
|
|
1609 |
|
1610 |
if (empty($info['mpeg']['audio'])) {
|
1611 |
|
1612 |
-
$
|
1613 |
if (isset($info['audio']['bitrate'])) {
|
1614 |
unset($info['audio']['bitrate']);
|
1615 |
}
|
@@ -1632,17 +1677,25 @@ class getid3_mp3 extends getid3_handler
|
|
1632 |
return true;
|
1633 |
}
|
1634 |
|
1635 |
-
|
|
|
|
|
1636 |
public static function MPEGaudioVersionArray() {
|
1637 |
static $MPEGaudioVersion = array('2.5', false, '2', '1');
|
1638 |
return $MPEGaudioVersion;
|
1639 |
}
|
1640 |
|
|
|
|
|
|
|
1641 |
public static function MPEGaudioLayerArray() {
|
1642 |
static $MPEGaudioLayer = array(false, 3, 2, 1);
|
1643 |
return $MPEGaudioLayer;
|
1644 |
}
|
1645 |
|
|
|
|
|
|
|
1646 |
public static function MPEGaudioBitrateArray() {
|
1647 |
static $MPEGaudioBitrate;
|
1648 |
if (empty($MPEGaudioBitrate)) {
|
@@ -1662,6 +1715,9 @@ class getid3_mp3 extends getid3_handler
|
|
1662 |
return $MPEGaudioBitrate;
|
1663 |
}
|
1664 |
|
|
|
|
|
|
|
1665 |
public static function MPEGaudioFrequencyArray() {
|
1666 |
static $MPEGaudioFrequency;
|
1667 |
if (empty($MPEGaudioFrequency)) {
|
@@ -1674,11 +1730,17 @@ class getid3_mp3 extends getid3_handler
|
|
1674 |
return $MPEGaudioFrequency;
|
1675 |
}
|
1676 |
|
|
|
|
|
|
|
1677 |
public static function MPEGaudioChannelModeArray() {
|
1678 |
static $MPEGaudioChannelMode = array('stereo', 'joint stereo', 'dual channel', 'mono');
|
1679 |
return $MPEGaudioChannelMode;
|
1680 |
}
|
1681 |
|
|
|
|
|
|
|
1682 |
public static function MPEGaudioModeExtensionArray() {
|
1683 |
static $MPEGaudioModeExtension;
|
1684 |
if (empty($MPEGaudioModeExtension)) {
|
@@ -1691,15 +1753,31 @@ class getid3_mp3 extends getid3_handler
|
|
1691 |
return $MPEGaudioModeExtension;
|
1692 |
}
|
1693 |
|
|
|
|
|
|
|
1694 |
public static function MPEGaudioEmphasisArray() {
|
1695 |
static $MPEGaudioEmphasis = array('none', '50/15ms', false, 'CCIT J.17');
|
1696 |
return $MPEGaudioEmphasis;
|
1697 |
}
|
1698 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1699 |
public static function MPEGaudioHeaderBytesValid($head4, $allowBitrate15=false) {
|
1700 |
return self::MPEGaudioHeaderValid(self::MPEGaudioHeaderDecode($head4), false, $allowBitrate15);
|
1701 |
}
|
1702 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1703 |
public static function MPEGaudioHeaderValid($rawarray, $echoerrors=false, $allowBitrate15=false) {
|
1704 |
if (($rawarray['synch'] & 0x0FFE) != 0x0FFE) {
|
1705 |
return false;
|
@@ -1772,6 +1850,11 @@ class getid3_mp3 extends getid3_handler
|
|
1772 |
return true;
|
1773 |
}
|
1774 |
|
|
|
|
|
|
|
|
|
|
|
1775 |
public static function MPEGaudioHeaderDecode($Header4Bytes) {
|
1776 |
// AAAA AAAA AAAB BCCD EEEE FFGH IIJJ KLMM
|
1777 |
// A - Frame sync (all bits set)
|
@@ -1809,6 +1892,15 @@ class getid3_mp3 extends getid3_handler
|
|
1809 |
return $MPEGrawHeader;
|
1810 |
}
|
1811 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1812 |
public static function MPEGaudioFrameLength(&$bitrate, &$version, &$layer, $padding, &$samplerate) {
|
1813 |
static $AudioFrameLengthCache = array();
|
1814 |
|
@@ -1870,6 +1962,11 @@ class getid3_mp3 extends getid3_handler
|
|
1870 |
return $AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate];
|
1871 |
}
|
1872 |
|
|
|
|
|
|
|
|
|
|
|
1873 |
public static function ClosestStandardMP3Bitrate($bit_rate) {
|
1874 |
static $standard_bit_rates = array (320000, 256000, 224000, 192000, 160000, 128000, 112000, 96000, 80000, 64000, 56000, 48000, 40000, 32000, 24000, 16000, 8000);
|
1875 |
static $bit_rate_table = array (0=>'-');
|
@@ -1890,10 +1987,16 @@ class getid3_mp3 extends getid3_handler
|
|
1890 |
return $bit_rate_table[$round_bit_rate];
|
1891 |
}
|
1892 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1893 |
public static function XingVBRidOffset($version, $channelmode) {
|
1894 |
static $XingVBRidOffsetCache = array();
|
1895 |
-
if (empty($
|
1896 |
-
$
|
1897 |
'1' => array ('mono' => 0x15, // 4 + 17 = 21
|
1898 |
'stereo' => 0x24, // 4 + 32 = 36
|
1899 |
'joint stereo' => 0x24,
|
@@ -1913,9 +2016,14 @@ class getid3_mp3 extends getid3_handler
|
|
1913 |
)
|
1914 |
);
|
1915 |
}
|
1916 |
-
return $
|
1917 |
}
|
1918 |
|
|
|
|
|
|
|
|
|
|
|
1919 |
public static function LAMEvbrMethodLookup($VBRmethodID) {
|
1920 |
static $LAMEvbrMethodLookup = array(
|
1921 |
0x00 => 'unknown',
|
@@ -1932,6 +2040,11 @@ class getid3_mp3 extends getid3_handler
|
|
1932 |
return (isset($LAMEvbrMethodLookup[$VBRmethodID]) ? $LAMEvbrMethodLookup[$VBRmethodID] : '');
|
1933 |
}
|
1934 |
|
|
|
|
|
|
|
|
|
|
|
1935 |
public static function LAMEmiscStereoModeLookup($StereoModeID) {
|
1936 |
static $LAMEmiscStereoModeLookup = array(
|
1937 |
0 => 'mono',
|
@@ -1946,6 +2059,11 @@ class getid3_mp3 extends getid3_handler
|
|
1946 |
return (isset($LAMEmiscStereoModeLookup[$StereoModeID]) ? $LAMEmiscStereoModeLookup[$StereoModeID] : '');
|
1947 |
}
|
1948 |
|
|
|
|
|
|
|
|
|
|
|
1949 |
public static function LAMEmiscSourceSampleFrequencyLookup($SourceSampleFrequencyID) {
|
1950 |
static $LAMEmiscSourceSampleFrequencyLookup = array(
|
1951 |
0 => '<= 32 kHz',
|
@@ -1956,6 +2074,11 @@ class getid3_mp3 extends getid3_handler
|
|
1956 |
return (isset($LAMEmiscSourceSampleFrequencyLookup[$SourceSampleFrequencyID]) ? $LAMEmiscSourceSampleFrequencyLookup[$SourceSampleFrequencyID] : '');
|
1957 |
}
|
1958 |
|
|
|
|
|
|
|
|
|
|
|
1959 |
public static function LAMEsurroundInfoLookup($SurroundInfoID) {
|
1960 |
static $LAMEsurroundInfoLookup = array(
|
1961 |
0 => 'no surround info',
|
@@ -1966,6 +2089,11 @@ class getid3_mp3 extends getid3_handler
|
|
1966 |
return (isset($LAMEsurroundInfoLookup[$SurroundInfoID]) ? $LAMEsurroundInfoLookup[$SurroundInfoID] : 'reserved');
|
1967 |
}
|
1968 |
|
|
|
|
|
|
|
|
|
|
|
1969 |
public static function LAMEpresetUsedLookup($LAMEtag) {
|
1970 |
|
1971 |
if ($LAMEtag['preset_used_id'] == 0) {
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.mp3.php //
|
24 |
|
25 |
class getid3_mp3 extends getid3_handler
|
26 |
{
|
27 |
+
/**
|
28 |
+
* Forces getID3() to scan the file byte-by-byte and log all the valid audio frame headers - extremely slow,
|
29 |
+
* unrecommended, but may provide data from otherwise-unusable files.
|
30 |
+
*
|
31 |
+
* @var bool
|
32 |
+
*/
|
33 |
+
public $allow_bruteforce = false;
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @return bool
|
37 |
+
*/
|
38 |
public function Analyze() {
|
39 |
$info = &$this->getid3->info;
|
40 |
|
42 |
|
43 |
if (!$this->getOnlyMPEGaudioInfo($info['avdataoffset'])) {
|
44 |
if ($this->allow_bruteforce) {
|
45 |
+
$this->error('Rescanning file in BruteForce mode');
|
46 |
+
$this->getOnlyMPEGaudioInfoBruteForce();
|
47 |
}
|
48 |
}
|
49 |
|
80 |
}
|
81 |
|
82 |
}
|
83 |
+
$this->warning($synchoffsetwarning);
|
84 |
|
85 |
}
|
86 |
|
142 |
break;
|
143 |
|
144 |
default:
|
145 |
+
$this->warning('Expecting [audio][dataformat] to be mp1/mp2/mp3 when fileformat == mp3, [audio][dataformat] actually "'.$info['audio']['dataformat'].'"');
|
146 |
break;
|
147 |
}
|
148 |
}
|
160 |
|
161 |
// Calculate playtime
|
162 |
if (!isset($info['playtime_seconds']) && isset($info['audio']['bitrate']) && ($info['audio']['bitrate'] > 0)) {
|
163 |
+
// https://github.com/JamesHeinrich/getID3/issues/161
|
164 |
+
// VBR header frame contains ~0.026s of silent audio data, but is not actually part of the original encoding and should be ignored
|
165 |
+
$xingVBRheaderFrameLength = ((isset($info['mpeg']['audio']['VBR_frames']) && isset($info['mpeg']['audio']['framelength'])) ? $info['mpeg']['audio']['framelength'] : 0);
|
166 |
+
|
167 |
+
$info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset'] - $xingVBRheaderFrameLength) * 8 / $info['audio']['bitrate'];
|
168 |
}
|
169 |
|
170 |
$info['audio']['encoder_options'] = $this->GuessEncoderOptions();
|
172 |
return true;
|
173 |
}
|
174 |
|
175 |
+
/**
|
176 |
+
* @return string
|
177 |
+
*/
|
178 |
public function GuessEncoderOptions() {
|
179 |
// shortcuts
|
180 |
$info = &$this->getid3->info;
|
181 |
+
$thisfile_mpeg_audio = array();
|
182 |
+
$thisfile_mpeg_audio_lame = array();
|
183 |
if (!empty($info['mpeg']['audio'])) {
|
184 |
$thisfile_mpeg_audio = &$info['mpeg']['audio'];
|
185 |
if (!empty($thisfile_mpeg_audio['LAME'])) {
|
194 |
|
195 |
$encoder_options = 'VBR q'.$thisfile_mpeg_audio['VBR_quality'];
|
196 |
|
197 |
+
} elseif (!empty($thisfile_mpeg_audio_lame['preset_used']) && isset($thisfile_mpeg_audio_lame['preset_used_id']) && (!in_array($thisfile_mpeg_audio_lame['preset_used_id'], $NamedPresetBitrates))) {
|
198 |
|
199 |
$encoder_options = $thisfile_mpeg_audio_lame['preset_used'];
|
200 |
|
420 |
return $encoder_options;
|
421 |
}
|
422 |
|
423 |
+
/**
|
424 |
+
* @param int $offset
|
425 |
+
* @param array $info
|
426 |
+
* @param bool $recursivesearch
|
427 |
+
* @param bool $ScanAsCBR
|
428 |
+
* @param bool $FastMPEGheaderScan
|
429 |
+
*
|
430 |
+
* @return bool
|
431 |
+
*/
|
432 |
public function decodeMPEGaudioHeader($offset, &$info, $recursivesearch=true, $ScanAsCBR=false, $FastMPEGheaderScan=false) {
|
433 |
static $MPEGaudioVersionLookup;
|
434 |
static $MPEGaudioLayerLookup;
|
448 |
}
|
449 |
|
450 |
if ($this->fseek($offset) != 0) {
|
451 |
+
$this->error('decodeMPEGaudioHeader() failed to seek to next offset at '.$offset);
|
452 |
return false;
|
453 |
}
|
454 |
//$headerstring = $this->fread(1441); // worst-case max length = 32kHz @ 320kbps layer 3 = 1441 bytes/frame
|
461 |
// and $cc... is the audio data
|
462 |
|
463 |
$head4 = substr($headerstring, 0, 4);
|
464 |
+
$head4_key = getid3_lib::PrintHexBytes($head4, true, false, false);
|
465 |
static $MPEGaudioHeaderDecodeCache = array();
|
466 |
+
if (isset($MPEGaudioHeaderDecodeCache[$head4_key])) {
|
467 |
+
$MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$head4_key];
|
468 |
} else {
|
469 |
$MPEGheaderRawArray = self::MPEGaudioHeaderDecode($head4);
|
470 |
+
$MPEGaudioHeaderDecodeCache[$head4_key] = $MPEGheaderRawArray;
|
471 |
}
|
472 |
|
473 |
static $MPEGaudioHeaderValidCache = array();
|
474 |
+
if (!isset($MPEGaudioHeaderValidCache[$head4_key])) { // Not in cache
|
475 |
+
//$MPEGaudioHeaderValidCache[$head4_key] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, true); // allow badly-formatted freeformat (from LAME 3.90 - 3.93.1)
|
476 |
+
$MPEGaudioHeaderValidCache[$head4_key] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, false);
|
477 |
}
|
478 |
|
479 |
// shortcut
|
482 |
}
|
483 |
$thisfile_mpeg_audio = &$info['mpeg']['audio'];
|
484 |
|
485 |
+
if ($MPEGaudioHeaderValidCache[$head4_key]) {
|
|
|
486 |
$thisfile_mpeg_audio['raw'] = $MPEGheaderRawArray;
|
487 |
} else {
|
488 |
+
$this->error('Invalid MPEG audio header ('.getid3_lib::PrintHexBytes($head4).') at offset '.$offset);
|
489 |
return false;
|
490 |
}
|
491 |
|
513 |
|
514 |
if ($thisfile_mpeg_audio['raw']['bitrate'] == 15) {
|
515 |
// http://www.hydrogenaudio.org/?act=ST&f=16&t=9682&st=0
|
516 |
+
$this->warning('Invalid bitrate index (15), this is a known bug in free-format MP3s encoded by LAME v3.90 - 3.93.1');
|
517 |
$thisfile_mpeg_audio['raw']['bitrate'] = 0;
|
518 |
}
|
519 |
$thisfile_mpeg_audio['padding'] = (bool) $thisfile_mpeg_audio['raw']['padding'];
|
535 |
if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] <= 192000)) {
|
536 |
// these are ok
|
537 |
} else {
|
538 |
+
$this->error($thisfile_mpeg_audio['bitrate'].'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.');
|
539 |
return false;
|
540 |
}
|
541 |
break;
|
546 |
if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] == 64000) || ($thisfile_mpeg_audio['bitrate'] >= 96000)) {
|
547 |
// these are ok
|
548 |
} else {
|
549 |
+
$this->error(intval(round($thisfile_mpeg_audio['bitrate'] / 1000)).'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.');
|
550 |
return false;
|
551 |
}
|
552 |
break;
|
568 |
if (isset($thisfile_mpeg_audio['framelength'])) {
|
569 |
$nextframetestoffset = $offset + $thisfile_mpeg_audio['framelength'];
|
570 |
} else {
|
571 |
+
$this->error('Frame at offset('.$offset.') is has an invalid frame length.');
|
572 |
return false;
|
573 |
}
|
574 |
|
585 |
|
586 |
$thisfile_mpeg_audio['bitrate_mode'] = 'vbr';
|
587 |
$thisfile_mpeg_audio['VBR_method'] = 'Fraunhofer';
|
588 |
+
$info['audio']['codec'] = 'Fraunhofer';
|
589 |
|
590 |
$SideInfoData = substr($headerstring, 4 + 2, 32);
|
591 |
|
678 |
$used_filesize = $thisfile_mpeg_audio['VBR_bytes'];
|
679 |
} elseif (!empty($info['filesize'])) {
|
680 |
$used_filesize = $info['filesize'];
|
681 |
+
$used_filesize -= (isset($info['id3v2']['headerlength']) ? intval($info['id3v2']['headerlength']) : 0);
|
682 |
$used_filesize -= (isset($info['id3v1']) ? 128 : 0);
|
683 |
$used_filesize -= (isset($info['tag_offset_end']) ? $info['tag_offset_end'] - $info['tag_offset_start'] : 0);
|
684 |
+
$this->warning('MP3.Xing header missing VBR_bytes, assuming MPEG audio portion of file is '.number_format($used_filesize).' bytes');
|
685 |
}
|
686 |
|
687 |
$framelengthfloat = $used_filesize / $thisfile_mpeg_audio['VBR_frames'];
|
871 |
$thisfile_mpeg_audio_lame['preset_used_id'] = ($PresetSurroundBytes & 0x07FF);
|
872 |
$thisfile_mpeg_audio_lame['preset_used'] = self::LAMEpresetUsedLookup($thisfile_mpeg_audio_lame);
|
873 |
if (!empty($thisfile_mpeg_audio_lame['preset_used_id']) && empty($thisfile_mpeg_audio_lame['preset_used'])) {
|
874 |
+
$this->warning('Unknown LAME preset used ('.$thisfile_mpeg_audio_lame['preset_used_id'].') - please report to info@getid3.org');
|
875 |
}
|
876 |
if (($thisfile_mpeg_audio_lame['short_version'] == 'LAME3.90.') && !empty($thisfile_mpeg_audio_lame['preset_used_id'])) {
|
877 |
// this may change if 3.90.4 ever comes out
|
915 |
$thisfile_mpeg_audio['bitrate_mode'] = 'cbr';
|
916 |
}
|
917 |
if ($thisfile_mpeg_audio['bitrate_mode'] == 'vbr') {
|
918 |
+
$this->warning('VBR file with no VBR header. Bitrate values calculated from actual frame bitrates.');
|
919 |
}
|
920 |
}
|
921 |
|
942 |
// $this->fseek($prenullbytefileoffset);
|
943 |
// if ($PossibleNullByte === "\x00") {
|
944 |
$info['avdataend']--;
|
945 |
+
// $this->warning('Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored');
|
946 |
// } else {
|
947 |
+
// $this->warning('Too much data in file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, found '.($info['avdataend'] - $info['avdataoffset']).' ('.(($info['avdataend'] - $info['avdataoffset']) - $ExpectedNumberOfAudioBytes).' bytes too many)');
|
948 |
// }
|
949 |
} else {
|
950 |
+
$this->warning('Too much data in file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, found '.($info['avdataend'] - $info['avdataoffset']).' ('.(($info['avdataend'] - $info['avdataoffset']) - $ExpectedNumberOfAudioBytes).' bytes too many)');
|
951 |
}
|
952 |
}
|
953 |
}
|
965 |
$info['audio']['bitrate'] = (($framebytelength - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 144;
|
966 |
}
|
967 |
} else {
|
968 |
+
$this->error('Error calculating frame length of free-format MP3 without Xing/LAME header');
|
969 |
}
|
970 |
}
|
971 |
}
|
1106 |
return true;
|
1107 |
}
|
1108 |
|
1109 |
+
/**
|
1110 |
+
* @param int $offset
|
1111 |
+
* @param int $nextframetestoffset
|
1112 |
+
* @param bool $ScanAsCBR
|
1113 |
+
*
|
1114 |
+
* @return bool
|
1115 |
+
*/
|
1116 |
public function RecursiveFrameScanning(&$offset, &$nextframetestoffset, $ScanAsCBR) {
|
1117 |
$info = &$this->getid3->info;
|
1118 |
+
$firstframetestarray = array('error' => array(), 'warning'=> array(), 'avdataend' => $info['avdataend'], 'avdataoffset' => $info['avdataoffset']);
|
1119 |
$this->decodeMPEGaudioHeader($offset, $firstframetestarray, false);
|
1120 |
|
1121 |
for ($i = 0; $i < GETID3_MP3_VALID_CHECK_FRAMES; $i++) {
|
1125 |
return true;
|
1126 |
}
|
1127 |
|
1128 |
+
$nextframetestarray = array('error' => array(), 'warning' => array(), 'avdataend' => $info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);
|
1129 |
if ($this->decodeMPEGaudioHeader($nextframetestoffset, $nextframetestarray, false)) {
|
1130 |
if ($ScanAsCBR) {
|
1131 |
// force CBR mode, used for trying to pick out invalid audio streams with valid(?) VBR headers, or VBR streams with no VBR header
|
1139 |
if (isset($nextframetestarray['mpeg']['audio']['framelength']) && ($nextframetestarray['mpeg']['audio']['framelength'] > 0)) {
|
1140 |
$nextframetestoffset += $nextframetestarray['mpeg']['audio']['framelength'];
|
1141 |
} else {
|
1142 |
+
$this->error('Frame at offset ('.$offset.') is has an invalid frame length.');
|
1143 |
return false;
|
1144 |
}
|
1145 |
|
1151 |
} else {
|
1152 |
|
1153 |
// next frame is not valid, note the error and fail, so scanning can contiue for a valid frame sequence
|
1154 |
+
$this->warning('Frame at offset ('.$offset.') is valid, but the next one at ('.$nextframetestoffset.') is not.');
|
1155 |
|
1156 |
return false;
|
1157 |
}
|
1159 |
return true;
|
1160 |
}
|
1161 |
|
1162 |
+
/**
|
1163 |
+
* @param int $offset
|
1164 |
+
* @param bool $deepscan
|
1165 |
+
*
|
1166 |
+
* @return int|false
|
1167 |
+
*/
|
1168 |
public function FreeFormatFrameLength($offset, $deepscan=false) {
|
1169 |
$info = &$this->getid3->info;
|
1170 |
|
1200 |
$framelength = $framelength2;
|
1201 |
}
|
1202 |
if (!$framelength) {
|
1203 |
+
$this->error('Cannot find next free-format synch pattern ('.getid3_lib::PrintHexBytes($SyncPattern1).' or '.getid3_lib::PrintHexBytes($SyncPattern2).') after offset '.$offset);
|
1204 |
return false;
|
1205 |
} else {
|
1206 |
+
$this->warning('ModeExtension varies between first frame and other frames (known free-format issue in LAME 3.88)');
|
1207 |
$info['audio']['codec'] = 'LAME';
|
1208 |
$info['audio']['encoder'] = 'LAME3.88';
|
1209 |
$SyncPattern1 = substr($SyncPattern1, 0, 3);
|
1230 |
$ActualFrameLengthValues[] = ($framelength + 1);
|
1231 |
$nextoffset++;
|
1232 |
} else {
|
1233 |
+
$this->error('Did not find expected free-format sync pattern at offset '.$nextoffset);
|
1234 |
return false;
|
1235 |
}
|
1236 |
$nextoffset += $framelength;
|
1242 |
return $framelength;
|
1243 |
}
|
1244 |
|
1245 |
+
/**
|
1246 |
+
* @return bool
|
1247 |
+
*/
|
1248 |
public function getOnlyMPEGaudioInfoBruteForce() {
|
1249 |
$MPEGaudioHeaderDecodeCache = array();
|
1250 |
$MPEGaudioHeaderValidCache = array();
|
1331 |
getid3_lib::safe_inc($Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]]);
|
1332 |
if ($max_frames_scan && (++$frames_scanned >= $max_frames_scan)) {
|
1333 |
$pct_data_scanned = ($this->ftell() - $info['avdataoffset']) / ($info['avdataend'] - $info['avdataoffset']);
|
1334 |
+
$this->warning('too many MPEG audio frames to scan, only scanned first '.$max_frames_scan.' frames ('.number_format($pct_data_scanned * 100, 1).'% of file) and extrapolated distribution, playtime and bitrate may be incorrect.');
|
1335 |
foreach ($Distribution as $key1 => $value1) {
|
1336 |
foreach ($value1 as $key2 => $value2) {
|
1337 |
$Distribution[$key1][$key2] = round($value2 / $pct_data_scanned);
|
1358 |
$info['mpeg']['audio']['version_distribution'] = $Distribution['version'];
|
1359 |
$info['mpeg']['audio']['padding_distribution'] = $Distribution['padding'];
|
1360 |
if (count($Distribution['version']) > 1) {
|
1361 |
+
$this->error('Corrupt file - more than one MPEG version detected');
|
1362 |
}
|
1363 |
if (count($Distribution['layer']) > 1) {
|
1364 |
+
$this->error('Corrupt file - more than one MPEG layer detected');
|
1365 |
}
|
1366 |
if (count($Distribution['frequency']) > 1) {
|
1367 |
+
$this->error('Corrupt file - more than one MPEG sample rate detected');
|
1368 |
}
|
1369 |
|
1370 |
|
1376 |
}
|
1377 |
$info['mpeg']['audio']['frame_count'] = array_sum($Distribution['bitrate']);
|
1378 |
if ($info['mpeg']['audio']['frame_count'] == 0) {
|
1379 |
+
$this->error('no MPEG audio frames found');
|
1380 |
return false;
|
1381 |
}
|
1382 |
$info['mpeg']['audio']['bitrate'] = ($bittotal / $info['mpeg']['audio']['frame_count']);
|
1392 |
return true;
|
1393 |
}
|
1394 |
|
1395 |
+
/**
|
1396 |
+
* @param int $avdataoffset
|
1397 |
+
* @param bool $BitrateHistogram
|
1398 |
+
*
|
1399 |
+
* @return bool
|
1400 |
+
*/
|
1401 |
public function getOnlyMPEGaudioInfo($avdataoffset, $BitrateHistogram=false) {
|
1402 |
// looks for synch, decodes MPEG audio header
|
1403 |
|
1407 |
static $MPEGaudioLayerLookup;
|
1408 |
static $MPEGaudioBitrateLookup;
|
1409 |
if (empty($MPEGaudioVersionLookup)) {
|
1410 |
+
$MPEGaudioVersionLookup = self::MPEGaudioVersionArray();
|
1411 |
+
$MPEGaudioLayerLookup = self::MPEGaudioLayerArray();
|
1412 |
+
$MPEGaudioBitrateLookup = self::MPEGaudioBitrateArray();
|
|
|
1413 |
}
|
1414 |
|
1415 |
$this->fseek($avdataoffset);
|
1416 |
$sync_seek_buffer_size = min(128 * 1024, $info['avdataend'] - $avdataoffset);
|
1417 |
if ($sync_seek_buffer_size <= 0) {
|
1418 |
+
$this->error('Invalid $sync_seek_buffer_size at offset '.$avdataoffset);
|
1419 |
return false;
|
1420 |
}
|
1421 |
$header = $this->fread($sync_seek_buffer_size);
|
1426 |
|
1427 |
if ($SynchSeekOffset > $sync_seek_buffer_size) {
|
1428 |
// if a synch's not found within the first 128k bytes, then give up
|
1429 |
+
$this->error('Could not find valid MPEG audio synch within the first '.round($sync_seek_buffer_size / 1024).'kB');
|
1430 |
if (isset($info['audio']['bitrate'])) {
|
1431 |
unset($info['audio']['bitrate']);
|
1432 |
}
|
1440 |
|
1441 |
} elseif (feof($this->getid3->fp)) {
|
1442 |
|
1443 |
+
$this->error('Could not find valid MPEG audio synch before end of file');
|
1444 |
if (isset($info['audio']['bitrate'])) {
|
1445 |
unset($info['audio']['bitrate']);
|
1446 |
}
|
1455 |
}
|
1456 |
|
1457 |
if (($SynchSeekOffset + 1) >= strlen($header)) {
|
1458 |
+
$this->error('Could not find valid MPEG synch before end of file');
|
1459 |
return false;
|
1460 |
}
|
1461 |
|
1462 |
if (($header{$SynchSeekOffset} == "\xFF") && ($header{($SynchSeekOffset + 1)} > "\xE0")) { // synch detected
|
1463 |
+
$FirstFrameAVDataOffset = null;
|
1464 |
if (!isset($FirstFrameThisfileInfo) && !isset($info['mpeg']['audio'])) {
|
1465 |
$FirstFrameThisfileInfo = $info;
|
1466 |
$FirstFrameAVDataOffset = $avdataoffset + $SynchSeekOffset;
|
1484 |
$info['audio']['dataformat'] = 'mp3';
|
1485 |
break;
|
1486 |
}
|
1487 |
+
if (isset($FirstFrameThisfileInfo) && isset($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode']) && ($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode'] == 'vbr')) {
|
1488 |
if (!(abs($info['audio']['bitrate'] - $FirstFrameThisfileInfo['audio']['bitrate']) <= 1)) {
|
1489 |
// If there is garbage data between a valid VBR header frame and a sequence
|
1490 |
// of valid MPEG-audio frames the VBR data is no longer discarded.
|
1499 |
if ($this->decodeMPEGaudioHeader($GarbageOffsetEnd, $dummy, true, true)) {
|
1500 |
$info = $dummy;
|
1501 |
$info['avdataoffset'] = $GarbageOffsetEnd;
|
1502 |
+
$this->warning('apparently-valid VBR header not used because could not find '.GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.'), but did find valid CBR stream starting at '.$GarbageOffsetEnd);
|
1503 |
} else {
|
1504 |
+
$this->warning('using data from VBR header even though could not find '.GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.')');
|
1505 |
}
|
1506 |
}
|
1507 |
}
|
1566 |
}
|
1567 |
}
|
1568 |
$synchstartoffset = $scan_start_offset[$current_segment];
|
1569 |
+
while (($synchstartoffset < $info['avdataend']) && $this->decodeMPEGaudioHeader($synchstartoffset, $dummy, false, false, $FastMode)) {
|
1570 |
$FastMode = true;
|
1571 |
$thisframebitrate = $MPEGaudioBitrateLookup[$MPEGaudioVersionLookup[$dummy['mpeg']['audio']['raw']['version']]][$MPEGaudioLayerLookup[$dummy['mpeg']['audio']['raw']['layer']]][$dummy['mpeg']['audio']['raw']['bitrate']];
|
1572 |
|
1594 |
}
|
1595 |
}
|
1596 |
if ($pct_data_scanned > 0) {
|
1597 |
+
$this->warning('too many MPEG audio frames to scan, only scanned '.$frames_scanned.' frames in '.$max_scan_segments.' segments ('.number_format($pct_data_scanned * 100, 1).'% of file) and extrapolated distribution, playtime and bitrate may be incorrect.');
|
1598 |
foreach ($info['mpeg']['audio'] as $key1 => $value1) {
|
1599 |
if (!preg_match('#_distribution$#i', $key1)) {
|
1600 |
continue;
|
1606 |
}
|
1607 |
|
1608 |
if ($SynchErrorsFound > 0) {
|
1609 |
+
$this->warning('Found '.$SynchErrorsFound.' synch errors in histogram analysis');
|
1610 |
//return false;
|
1611 |
}
|
1612 |
|
1619 |
}
|
1620 |
}
|
1621 |
if ($framecounter == 0) {
|
1622 |
+
$this->error('Corrupt MP3 file: framecounter == zero');
|
1623 |
return false;
|
1624 |
}
|
1625 |
$info['mpeg']['audio']['frame_count'] = getid3_lib::CastAsInt($framecounter);
|
1654 |
|
1655 |
if (empty($info['mpeg']['audio'])) {
|
1656 |
|
1657 |
+
$this->error('could not find valid MPEG synch before end of file');
|
1658 |
if (isset($info['audio']['bitrate'])) {
|
1659 |
unset($info['audio']['bitrate']);
|
1660 |
}
|
1677 |
return true;
|
1678 |
}
|
1679 |
|
1680 |
+
/**
|
1681 |
+
* @return array
|
1682 |
+
*/
|
1683 |
public static function MPEGaudioVersionArray() {
|
1684 |
static $MPEGaudioVersion = array('2.5', false, '2', '1');
|
1685 |
return $MPEGaudioVersion;
|
1686 |
}
|
1687 |
|
1688 |
+
/**
|
1689 |
+
* @return array
|
1690 |
+
*/
|
1691 |
public static function MPEGaudioLayerArray() {
|
1692 |
static $MPEGaudioLayer = array(false, 3, 2, 1);
|
1693 |
return $MPEGaudioLayer;
|
1694 |
}
|
1695 |
|
1696 |
+
/**
|
1697 |
+
* @return array
|
1698 |
+
*/
|
1699 |
public static function MPEGaudioBitrateArray() {
|
1700 |
static $MPEGaudioBitrate;
|
1701 |
if (empty($MPEGaudioBitrate)) {
|
1715 |
return $MPEGaudioBitrate;
|
1716 |
}
|
1717 |
|
1718 |
+
/**
|
1719 |
+
* @return array
|
1720 |
+
*/
|
1721 |
public static function MPEGaudioFrequencyArray() {
|
1722 |
static $MPEGaudioFrequency;
|
1723 |
if (empty($MPEGaudioFrequency)) {
|
1730 |
return $MPEGaudioFrequency;
|
1731 |
}
|
1732 |
|
1733 |
+
/**
|
1734 |
+
* @return array
|
1735 |
+
*/
|
1736 |
public static function MPEGaudioChannelModeArray() {
|
1737 |
static $MPEGaudioChannelMode = array('stereo', 'joint stereo', 'dual channel', 'mono');
|
1738 |
return $MPEGaudioChannelMode;
|
1739 |
}
|
1740 |
|
1741 |
+
/**
|
1742 |
+
* @return array
|
1743 |
+
*/
|
1744 |
public static function MPEGaudioModeExtensionArray() {
|
1745 |
static $MPEGaudioModeExtension;
|
1746 |
if (empty($MPEGaudioModeExtension)) {
|
1753 |
return $MPEGaudioModeExtension;
|
1754 |
}
|
1755 |
|
1756 |
+
/**
|
1757 |
+
* @return array
|
1758 |
+
*/
|
1759 |
public static function MPEGaudioEmphasisArray() {
|
1760 |
static $MPEGaudioEmphasis = array('none', '50/15ms', false, 'CCIT J.17');
|
1761 |
return $MPEGaudioEmphasis;
|
1762 |
}
|
1763 |
|
1764 |
+
/**
|
1765 |
+
* @param string $head4
|
1766 |
+
* @param bool $allowBitrate15
|
1767 |
+
*
|
1768 |
+
* @return bool
|
1769 |
+
*/
|
1770 |
public static function MPEGaudioHeaderBytesValid($head4, $allowBitrate15=false) {
|
1771 |
return self::MPEGaudioHeaderValid(self::MPEGaudioHeaderDecode($head4), false, $allowBitrate15);
|
1772 |
}
|
1773 |
|
1774 |
+
/**
|
1775 |
+
* @param array $rawarray
|
1776 |
+
* @param bool $echoerrors
|
1777 |
+
* @param bool $allowBitrate15
|
1778 |
+
*
|
1779 |
+
* @return bool
|
1780 |
+
*/
|
1781 |
public static function MPEGaudioHeaderValid($rawarray, $echoerrors=false, $allowBitrate15=false) {
|
1782 |
if (($rawarray['synch'] & 0x0FFE) != 0x0FFE) {
|
1783 |
return false;
|
1850 |
return true;
|
1851 |
}
|
1852 |
|
1853 |
+
/**
|
1854 |
+
* @param string $Header4Bytes
|
1855 |
+
*
|
1856 |
+
* @return array|false
|
1857 |
+
*/
|
1858 |
public static function MPEGaudioHeaderDecode($Header4Bytes) {
|
1859 |
// AAAA AAAA AAAB BCCD EEEE FFGH IIJJ KLMM
|
1860 |
// A - Frame sync (all bits set)
|
1892 |
return $MPEGrawHeader;
|
1893 |
}
|
1894 |
|
1895 |
+
/**
|
1896 |
+
* @param int|string $bitrate
|
1897 |
+
* @param string $version
|
1898 |
+
* @param string $layer
|
1899 |
+
* @param bool $padding
|
1900 |
+
* @param int $samplerate
|
1901 |
+
*
|
1902 |
+
* @return int|false
|
1903 |
+
*/
|
1904 |
public static function MPEGaudioFrameLength(&$bitrate, &$version, &$layer, $padding, &$samplerate) {
|
1905 |
static $AudioFrameLengthCache = array();
|
1906 |
|
1962 |
return $AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate];
|
1963 |
}
|
1964 |
|
1965 |
+
/**
|
1966 |
+
* @param float|int $bit_rate
|
1967 |
+
*
|
1968 |
+
* @return int|float|string
|
1969 |
+
*/
|
1970 |
public static function ClosestStandardMP3Bitrate($bit_rate) {
|
1971 |
static $standard_bit_rates = array (320000, 256000, 224000, 192000, 160000, 128000, 112000, 96000, 80000, 64000, 56000, 48000, 40000, 32000, 24000, 16000, 8000);
|
1972 |
static $bit_rate_table = array (0=>'-');
|
1987 |
return $bit_rate_table[$round_bit_rate];
|
1988 |
}
|
1989 |
|
1990 |
+
/**
|
1991 |
+
* @param string $version
|
1992 |
+
* @param string $channelmode
|
1993 |
+
*
|
1994 |
+
* @return int
|
1995 |
+
*/
|
1996 |
public static function XingVBRidOffset($version, $channelmode) {
|
1997 |
static $XingVBRidOffsetCache = array();
|
1998 |
+
if (empty($XingVBRidOffsetCache)) {
|
1999 |
+
$XingVBRidOffsetCache = array (
|
2000 |
'1' => array ('mono' => 0x15, // 4 + 17 = 21
|
2001 |
'stereo' => 0x24, // 4 + 32 = 36
|
2002 |
'joint stereo' => 0x24,
|
2016 |
)
|
2017 |
);
|
2018 |
}
|
2019 |
+
return $XingVBRidOffsetCache[$version][$channelmode];
|
2020 |
}
|
2021 |
|
2022 |
+
/**
|
2023 |
+
* @param int $VBRmethodID
|
2024 |
+
*
|
2025 |
+
* @return string
|
2026 |
+
*/
|
2027 |
public static function LAMEvbrMethodLookup($VBRmethodID) {
|
2028 |
static $LAMEvbrMethodLookup = array(
|
2029 |
0x00 => 'unknown',
|
2040 |
return (isset($LAMEvbrMethodLookup[$VBRmethodID]) ? $LAMEvbrMethodLookup[$VBRmethodID] : '');
|
2041 |
}
|
2042 |
|
2043 |
+
/**
|
2044 |
+
* @param int $StereoModeID
|
2045 |
+
*
|
2046 |
+
* @return string
|
2047 |
+
*/
|
2048 |
public static function LAMEmiscStereoModeLookup($StereoModeID) {
|
2049 |
static $LAMEmiscStereoModeLookup = array(
|
2050 |
0 => 'mono',
|
2059 |
return (isset($LAMEmiscStereoModeLookup[$StereoModeID]) ? $LAMEmiscStereoModeLookup[$StereoModeID] : '');
|
2060 |
}
|
2061 |
|
2062 |
+
/**
|
2063 |
+
* @param int $SourceSampleFrequencyID
|
2064 |
+
*
|
2065 |
+
* @return string
|
2066 |
+
*/
|
2067 |
public static function LAMEmiscSourceSampleFrequencyLookup($SourceSampleFrequencyID) {
|
2068 |
static $LAMEmiscSourceSampleFrequencyLookup = array(
|
2069 |
0 => '<= 32 kHz',
|
2074 |
return (isset($LAMEmiscSourceSampleFrequencyLookup[$SourceSampleFrequencyID]) ? $LAMEmiscSourceSampleFrequencyLookup[$SourceSampleFrequencyID] : '');
|
2075 |
}
|
2076 |
|
2077 |
+
/**
|
2078 |
+
* @param int $SurroundInfoID
|
2079 |
+
*
|
2080 |
+
* @return string
|
2081 |
+
*/
|
2082 |
public static function LAMEsurroundInfoLookup($SurroundInfoID) {
|
2083 |
static $LAMEsurroundInfoLookup = array(
|
2084 |
0 => 'no surround info',
|
2089 |
return (isset($LAMEsurroundInfoLookup[$SurroundInfoID]) ? $LAMEsurroundInfoLookup[$SurroundInfoID] : 'reserved');
|
2090 |
}
|
2091 |
|
2092 |
+
/**
|
2093 |
+
* @param array $LAMEtag
|
2094 |
+
*
|
2095 |
+
* @return string
|
2096 |
+
*/
|
2097 |
public static function LAMEpresetUsedLookup($LAMEtag) {
|
2098 |
|
2099 |
if ($LAMEtag['preset_used_id'] == 0) {
|
lib/getid3/module.audio.mpc.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.mpc.php //
|
@@ -17,7 +17,9 @@
|
|
17 |
|
18 |
class getid3_mpc extends getid3_handler
|
19 |
{
|
20 |
-
|
|
|
|
|
21 |
public function Analyze() {
|
22 |
$info = &$this->getid3->info;
|
23 |
|
@@ -50,16 +52,17 @@ class getid3_mpc extends getid3_handler
|
|
50 |
|
51 |
} else {
|
52 |
|
53 |
-
$
|
54 |
unset($info['fileformat']);
|
55 |
unset($info['mpc']);
|
56 |
return false;
|
57 |
|
58 |
}
|
59 |
-
return false;
|
60 |
}
|
61 |
|
62 |
-
|
|
|
|
|
63 |
public function ParseMPCsv8() {
|
64 |
// this is SV8
|
65 |
// http://trac.musepack.net/trac/wiki/SV8Specification
|
@@ -83,13 +86,13 @@ class getid3_mpc extends getid3_handler
|
|
83 |
$thisPacket['key'] = substr($MPCheaderData, 0, $keyNameSize);
|
84 |
$thisPacket['key_name'] = $this->MPCsv8PacketName($thisPacket['key']);
|
85 |
if ($thisPacket['key'] == $thisPacket['key_name']) {
|
86 |
-
$
|
87 |
return false;
|
88 |
}
|
89 |
$packetLength = 0;
|
90 |
$thisPacket['packet_size'] = $this->SV8variableLengthInteger(substr($MPCheaderData, $keyNameSize), $packetLength); // includes keyname and packet_size field
|
91 |
if ($thisPacket['packet_size'] === false) {
|
92 |
-
$
|
93 |
return false;
|
94 |
}
|
95 |
$packet_offset += $packetLength;
|
@@ -195,7 +198,7 @@ class getid3_mpc extends getid3_handler
|
|
195 |
break;
|
196 |
|
197 |
default:
|
198 |
-
$
|
199 |
return false;
|
200 |
break;
|
201 |
}
|
@@ -208,6 +211,9 @@ class getid3_mpc extends getid3_handler
|
|
208 |
return true;
|
209 |
}
|
210 |
|
|
|
|
|
|
|
211 |
public function ParseMPCsv7() {
|
212 |
// this is SV7
|
213 |
// http://www.uni-jena.de/~pfk/mpp/sv8/header.html
|
@@ -229,7 +235,7 @@ class getid3_mpc extends getid3_handler
|
|
229 |
$offset += 4;
|
230 |
|
231 |
if ($thisfile_mpc_header['stream_version_major'] != 7) {
|
232 |
-
$
|
233 |
return false;
|
234 |
}
|
235 |
|
@@ -268,7 +274,7 @@ class getid3_mpc extends getid3_handler
|
|
268 |
$thisfile_mpc_header['profile'] = $this->MPCprofileNameLookup($thisfile_mpc_header['raw']['profile']);
|
269 |
$thisfile_mpc_header['sample_rate'] = $this->MPCfrequencyLookup($thisfile_mpc_header['raw']['sample_rate']);
|
270 |
if ($thisfile_mpc_header['sample_rate'] == 0) {
|
271 |
-
$
|
272 |
return false;
|
273 |
}
|
274 |
$info['audio']['sample_rate'] = $thisfile_mpc_header['sample_rate'];
|
@@ -276,7 +282,7 @@ class getid3_mpc extends getid3_handler
|
|
276 |
|
277 |
$info['playtime_seconds'] = ($thisfile_mpc_header['samples'] / $info['audio']['channels']) / $info['audio']['sample_rate'];
|
278 |
if ($info['playtime_seconds'] == 0) {
|
279 |
-
$
|
280 |
return false;
|
281 |
}
|
282 |
|
@@ -322,6 +328,9 @@ class getid3_mpc extends getid3_handler
|
|
322 |
return true;
|
323 |
}
|
324 |
|
|
|
|
|
|
|
325 |
public function ParseMPCsv6() {
|
326 |
// this is SV4 - SV6
|
327 |
|
@@ -377,7 +386,7 @@ class getid3_mpc extends getid3_handler
|
|
377 |
}
|
378 |
|
379 |
if (($thisfile_mpc_header['stream_version_major'] > 4) && ($thisfile_mpc_header['block_size'] != 1)) {
|
380 |
-
$
|
381 |
}
|
382 |
|
383 |
$thisfile_mpc_header['sample_rate'] = 44100; // AB: used by all files up to SV7
|
@@ -397,7 +406,11 @@ class getid3_mpc extends getid3_handler
|
|
397 |
return true;
|
398 |
}
|
399 |
|
400 |
-
|
|
|
|
|
|
|
|
|
401 |
public function MPCprofileNameLookup($profileid) {
|
402 |
static $MPCprofileNameLookup = array(
|
403 |
0 => 'no profile',
|
@@ -420,6 +433,11 @@ class getid3_mpc extends getid3_handler
|
|
420 |
return (isset($MPCprofileNameLookup[$profileid]) ? $MPCprofileNameLookup[$profileid] : 'invalid');
|
421 |
}
|
422 |
|
|
|
|
|
|
|
|
|
|
|
423 |
public function MPCfrequencyLookup($frequencyid) {
|
424 |
static $MPCfrequencyLookup = array(
|
425 |
0 => 44100,
|
@@ -430,6 +448,11 @@ class getid3_mpc extends getid3_handler
|
|
430 |
return (isset($MPCfrequencyLookup[$frequencyid]) ? $MPCfrequencyLookup[$frequencyid] : 'invalid');
|
431 |
}
|
432 |
|
|
|
|
|
|
|
|
|
|
|
433 |
public function MPCpeakDBLookup($intvalue) {
|
434 |
if ($intvalue > 0) {
|
435 |
return ((log10($intvalue) / log10(2)) - 15) * 6;
|
@@ -437,6 +460,11 @@ class getid3_mpc extends getid3_handler
|
|
437 |
return false;
|
438 |
}
|
439 |
|
|
|
|
|
|
|
|
|
|
|
440 |
public function MPCencoderVersionLookup($encoderversion) {
|
441 |
//Encoder version * 100 (106 = 1.06)
|
442 |
//EncoderVersion % 10 == 0 Release (1.0)
|
@@ -464,6 +492,13 @@ class getid3_mpc extends getid3_handler
|
|
464 |
return number_format($encoderversion / 100, 2).' alpha';
|
465 |
}
|
466 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
467 |
public function SV8variableLengthInteger($data, &$packetLength, $maxHandledPacketLength=9) {
|
468 |
$packet_size = 0;
|
469 |
for ($packetLength = 1; $packetLength <= $maxHandledPacketLength; $packetLength++) {
|
@@ -488,6 +523,11 @@ class getid3_mpc extends getid3_handler
|
|
488 |
return $packet_size;
|
489 |
}
|
490 |
|
|
|
|
|
|
|
|
|
|
|
491 |
public function MPCsv8PacketName($packetKey) {
|
492 |
static $MPCsv8PacketName = array();
|
493 |
if (empty($MPCsv8PacketName)) {
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.mpc.php //
|
17 |
|
18 |
class getid3_mpc extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @return bool
|
22 |
+
*/
|
23 |
public function Analyze() {
|
24 |
$info = &$this->getid3->info;
|
25 |
|
52 |
|
53 |
} else {
|
54 |
|
55 |
+
$this->error('Expecting "MP+" or "MPCK" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($MPCheaderData, 0, 4)).'"');
|
56 |
unset($info['fileformat']);
|
57 |
unset($info['mpc']);
|
58 |
return false;
|
59 |
|
60 |
}
|
|
|
61 |
}
|
62 |
|
63 |
+
/**
|
64 |
+
* @return bool
|
65 |
+
*/
|
66 |
public function ParseMPCsv8() {
|
67 |
// this is SV8
|
68 |
// http://trac.musepack.net/trac/wiki/SV8Specification
|
86 |
$thisPacket['key'] = substr($MPCheaderData, 0, $keyNameSize);
|
87 |
$thisPacket['key_name'] = $this->MPCsv8PacketName($thisPacket['key']);
|
88 |
if ($thisPacket['key'] == $thisPacket['key_name']) {
|
89 |
+
$this->error('Found unexpected key value "'.$thisPacket['key'].'" at offset '.$thisPacket['offset']);
|
90 |
return false;
|
91 |
}
|
92 |
$packetLength = 0;
|
93 |
$thisPacket['packet_size'] = $this->SV8variableLengthInteger(substr($MPCheaderData, $keyNameSize), $packetLength); // includes keyname and packet_size field
|
94 |
if ($thisPacket['packet_size'] === false) {
|
95 |
+
$this->error('Did not find expected packet length within '.$maxHandledPacketLength.' bytes at offset '.($thisPacket['offset'] + $keyNameSize));
|
96 |
return false;
|
97 |
}
|
98 |
$packet_offset += $packetLength;
|
198 |
break;
|
199 |
|
200 |
default:
|
201 |
+
$this->error('Found unhandled key type "'.$thisPacket['key'].'" at offset '.$thisPacket['offset']);
|
202 |
return false;
|
203 |
break;
|
204 |
}
|
211 |
return true;
|
212 |
}
|
213 |
|
214 |
+
/**
|
215 |
+
* @return bool
|
216 |
+
*/
|
217 |
public function ParseMPCsv7() {
|
218 |
// this is SV7
|
219 |
// http://www.uni-jena.de/~pfk/mpp/sv8/header.html
|
235 |
$offset += 4;
|
236 |
|
237 |
if ($thisfile_mpc_header['stream_version_major'] != 7) {
|
238 |
+
$this->error('Only Musepack SV7 supported (this file claims to be v'.$thisfile_mpc_header['stream_version_major'].')');
|
239 |
return false;
|
240 |
}
|
241 |
|
274 |
$thisfile_mpc_header['profile'] = $this->MPCprofileNameLookup($thisfile_mpc_header['raw']['profile']);
|
275 |
$thisfile_mpc_header['sample_rate'] = $this->MPCfrequencyLookup($thisfile_mpc_header['raw']['sample_rate']);
|
276 |
if ($thisfile_mpc_header['sample_rate'] == 0) {
|
277 |
+
$this->error('Corrupt MPC file: frequency == zero');
|
278 |
return false;
|
279 |
}
|
280 |
$info['audio']['sample_rate'] = $thisfile_mpc_header['sample_rate'];
|
282 |
|
283 |
$info['playtime_seconds'] = ($thisfile_mpc_header['samples'] / $info['audio']['channels']) / $info['audio']['sample_rate'];
|
284 |
if ($info['playtime_seconds'] == 0) {
|
285 |
+
$this->error('Corrupt MPC file: playtime_seconds == zero');
|
286 |
return false;
|
287 |
}
|
288 |
|
328 |
return true;
|
329 |
}
|
330 |
|
331 |
+
/**
|
332 |
+
* @return bool
|
333 |
+
*/
|
334 |
public function ParseMPCsv6() {
|
335 |
// this is SV4 - SV6
|
336 |
|
386 |
}
|
387 |
|
388 |
if (($thisfile_mpc_header['stream_version_major'] > 4) && ($thisfile_mpc_header['block_size'] != 1)) {
|
389 |
+
$this->warning('Block size expected to be 1, actual value found: '.$thisfile_mpc_header['block_size']);
|
390 |
}
|
391 |
|
392 |
$thisfile_mpc_header['sample_rate'] = 44100; // AB: used by all files up to SV7
|
406 |
return true;
|
407 |
}
|
408 |
|
409 |
+
/**
|
410 |
+
* @param int $profileid
|
411 |
+
*
|
412 |
+
* @return string
|
413 |
+
*/
|
414 |
public function MPCprofileNameLookup($profileid) {
|
415 |
static $MPCprofileNameLookup = array(
|
416 |
0 => 'no profile',
|
433 |
return (isset($MPCprofileNameLookup[$profileid]) ? $MPCprofileNameLookup[$profileid] : 'invalid');
|
434 |
}
|
435 |
|
436 |
+
/**
|
437 |
+
* @param int $frequencyid
|
438 |
+
*
|
439 |
+
* @return int|string
|
440 |
+
*/
|
441 |
public function MPCfrequencyLookup($frequencyid) {
|
442 |
static $MPCfrequencyLookup = array(
|
443 |
0 => 44100,
|
448 |
return (isset($MPCfrequencyLookup[$frequencyid]) ? $MPCfrequencyLookup[$frequencyid] : 'invalid');
|
449 |
}
|
450 |
|
451 |
+
/**
|
452 |
+
* @param int $intvalue
|
453 |
+
*
|
454 |
+
* @return float|false
|
455 |
+
*/
|
456 |
public function MPCpeakDBLookup($intvalue) {
|
457 |
if ($intvalue > 0) {
|
458 |
return ((log10($intvalue) / log10(2)) - 15) * 6;
|
460 |
return false;
|
461 |
}
|
462 |
|
463 |
+
/**
|
464 |
+
* @param int $encoderversion
|
465 |
+
*
|
466 |
+
* @return string
|
467 |
+
*/
|
468 |
public function MPCencoderVersionLookup($encoderversion) {
|
469 |
//Encoder version * 100 (106 = 1.06)
|
470 |
//EncoderVersion % 10 == 0 Release (1.0)
|
492 |
return number_format($encoderversion / 100, 2).' alpha';
|
493 |
}
|
494 |
|
495 |
+
/**
|
496 |
+
* @param string $data
|
497 |
+
* @param int $packetLength
|
498 |
+
* @param int $maxHandledPacketLength
|
499 |
+
*
|
500 |
+
* @return int|false
|
501 |
+
*/
|
502 |
public function SV8variableLengthInteger($data, &$packetLength, $maxHandledPacketLength=9) {
|
503 |
$packet_size = 0;
|
504 |
for ($packetLength = 1; $packetLength <= $maxHandledPacketLength; $packetLength++) {
|
523 |
return $packet_size;
|
524 |
}
|
525 |
|
526 |
+
/**
|
527 |
+
* @param string $packetKey
|
528 |
+
*
|
529 |
+
* @return string
|
530 |
+
*/
|
531 |
public function MPCsv8PacketName($packetKey) {
|
532 |
static $MPCsv8PacketName = array();
|
533 |
if (empty($MPCsv8PacketName)) {
|
lib/getid3/module.audio.ogg.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.ogg.php //
|
@@ -18,7 +18,11 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.flac.php', __FILE
|
|
18 |
|
19 |
class getid3_ogg extends getid3_handler
|
20 |
{
|
21 |
-
|
|
|
|
|
|
|
|
|
22 |
public function Analyze() {
|
23 |
$info = &$this->getid3->info;
|
24 |
|
@@ -26,13 +30,13 @@ class getid3_ogg extends getid3_handler
|
|
26 |
|
27 |
// Warn about illegal tags - only vorbiscomments are allowed
|
28 |
if (isset($info['id3v2'])) {
|
29 |
-
$
|
30 |
}
|
31 |
if (isset($info['id3v1'])) {
|
32 |
-
$
|
33 |
}
|
34 |
if (isset($info['ape'])) {
|
35 |
-
$
|
36 |
}
|
37 |
|
38 |
|
@@ -44,7 +48,7 @@ class getid3_ogg extends getid3_handler
|
|
44 |
$info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
|
45 |
|
46 |
if ($this->ftell() >= $this->getid3->fread_buffer_size()) {
|
47 |
-
$
|
48 |
unset($info['fileformat']);
|
49 |
unset($info['ogg']);
|
50 |
return false;
|
@@ -65,7 +69,7 @@ class getid3_ogg extends getid3_handler
|
|
65 |
|
66 |
} elseif (substr($filedata, 0, 8) == 'OpusHead') {
|
67 |
|
68 |
-
if(
|
69 |
return false;
|
70 |
}
|
71 |
|
@@ -179,7 +183,7 @@ class getid3_ogg extends getid3_handler
|
|
179 |
if ($info['ogg']['pageheader']['theora']['pixel_aspect_denominator'] > 0) {
|
180 |
$info['video']['pixel_aspect_ratio'] = (float) $info['ogg']['pageheader']['theora']['pixel_aspect_numerator'] / $info['ogg']['pageheader']['theora']['pixel_aspect_denominator'];
|
181 |
}
|
182 |
-
$
|
183 |
|
184 |
|
185 |
} elseif (substr($filedata, 0, 8) == "fishead\x00") {
|
@@ -240,7 +244,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
240 |
} elseif (substr($filedata, 1, 6) == 'theora') {
|
241 |
|
242 |
$info['video']['dataformat'] = 'theora1';
|
243 |
-
$
|
244 |
//break;
|
245 |
|
246 |
} elseif (substr($filedata, 1, 6) == 'vorbis') {
|
@@ -248,7 +252,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
248 |
$this->ParseVorbisPageHeader($filedata, $filedataoffset, $oggpageinfo);
|
249 |
|
250 |
} else {
|
251 |
-
$
|
252 |
//break;
|
253 |
}
|
254 |
//} while ($oggpageinfo['page_seqno'] == 0);
|
@@ -256,12 +260,37 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
256 |
|
257 |
$this->fseek($oggpageinfo['page_start_offset']);
|
258 |
|
259 |
-
$
|
260 |
//return false;
|
261 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
262 |
} else {
|
263 |
|
264 |
-
$
|
265 |
unset($info['ogg']);
|
266 |
unset($info['mime_type']);
|
267 |
return false;
|
@@ -284,7 +313,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
284 |
case 'flac':
|
285 |
$flac = new getid3_flac($this->getid3);
|
286 |
if (!$flac->parseMETAdata()) {
|
287 |
-
$
|
288 |
return false;
|
289 |
}
|
290 |
unset($flac);
|
@@ -299,7 +328,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
299 |
$filedata = $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
|
300 |
$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] = substr($filedata, 0, 8); // hard-coded to 'OpusTags'
|
301 |
if(substr($filedata, 0, 8) != 'OpusTags') {
|
302 |
-
$
|
303 |
return false;
|
304 |
}
|
305 |
|
@@ -311,7 +340,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
311 |
// Last Page - Number of Samples
|
312 |
if (!getid3_lib::intValueSupported($info['avdataend'])) {
|
313 |
|
314 |
-
$
|
315 |
|
316 |
} else {
|
317 |
|
@@ -323,7 +352,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
323 |
$info['ogg']['pageheader']['eos'] = $this->ParseOggPageHeader();
|
324 |
$info['ogg']['samples'] = $info['ogg']['pageheader']['eos']['pcm_abs_position'];
|
325 |
if ($info['ogg']['samples'] == 0) {
|
326 |
-
$
|
327 |
return false;
|
328 |
}
|
329 |
if (!empty($info['audio']['sample_rate'])) {
|
@@ -342,7 +371,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
342 |
}
|
343 |
if (isset($info['audio']['bitrate']) && !isset($info['playtime_seconds'])) {
|
344 |
if ($info['audio']['bitrate'] == 0) {
|
345 |
-
$
|
346 |
return false;
|
347 |
}
|
348 |
$info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $info['audio']['bitrate']);
|
@@ -378,6 +407,13 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
378 |
return true;
|
379 |
}
|
380 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
381 |
public function ParseVorbisPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo) {
|
382 |
$info = &$this->getid3->info;
|
383 |
$info['audio']['dataformat'] = 'vorbis';
|
@@ -395,7 +431,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
395 |
$info['ogg']['samplerate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
396 |
$filedataoffset += 4;
|
397 |
if ($info['ogg']['samplerate'] == 0) {
|
398 |
-
$
|
399 |
return false;
|
400 |
}
|
401 |
$info['audio']['sample_rate'] = $info['ogg']['samplerate'];
|
@@ -426,7 +462,15 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
426 |
return true;
|
427 |
}
|
428 |
|
429 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
430 |
public function ParseOpusPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo) {
|
431 |
$info = &$this->getid3->info;
|
432 |
$info['audio']['dataformat'] = 'opus';
|
@@ -443,7 +487,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
443 |
$filedataoffset += 1;
|
444 |
|
445 |
if ($info['ogg']['pageheader']['opus']['version'] < 1 || $info['ogg']['pageheader']['opus']['version'] > 15) {
|
446 |
-
$
|
447 |
return false;
|
448 |
}
|
449 |
|
@@ -451,14 +495,14 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
451 |
$filedataoffset += 1;
|
452 |
|
453 |
if ($info['ogg']['pageheader']['opus']['out_channel_count'] == 0) {
|
454 |
-
$
|
455 |
return false;
|
456 |
}
|
457 |
|
458 |
$info['ogg']['pageheader']['opus']['pre_skip'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2));
|
459 |
$filedataoffset += 2;
|
460 |
|
461 |
-
$info['ogg']['pageheader']['opus']['
|
462 |
$filedataoffset += 4;
|
463 |
|
464 |
//$info['ogg']['pageheader']['opus']['output_gain'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2));
|
@@ -467,16 +511,19 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
467 |
//$info['ogg']['pageheader']['opus']['channel_mapping_family'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
|
468 |
//$filedataoffset += 1;
|
469 |
|
470 |
-
$info['opus']['opus_version']
|
471 |
-
$info['opus']['
|
472 |
-
$info['opus']['out_channel_count']
|
473 |
|
474 |
-
$info['audio']['channels']
|
475 |
-
$info['audio']['
|
|
|
476 |
return true;
|
477 |
}
|
478 |
|
479 |
-
|
|
|
|
|
480 |
public function ParseOggPageHeader() {
|
481 |
// http://xiph.org/ogg/vorbis/doc/framing.html
|
482 |
$oggheader['page_start_offset'] = $this->ftell(); // where we started from in the file
|
@@ -489,7 +536,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
489 |
return false;
|
490 |
}
|
491 |
if ((($filedataoffset + 28) > strlen($filedata)) || (strlen($filedata) < 28)) {
|
492 |
-
if ($this->feof() || (($filedata .= $this->fread($this->getid3->fread_buffer_size())) ===
|
493 |
// get some more data, unless eof, in which case fail
|
494 |
return false;
|
495 |
}
|
@@ -528,13 +575,19 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
528 |
return $oggheader;
|
529 |
}
|
530 |
|
531 |
-
|
|
|
|
|
|
|
|
|
532 |
public function ParseVorbisComments() {
|
533 |
$info = &$this->getid3->info;
|
534 |
|
535 |
$OriginalOffset = $this->ftell();
|
|
|
536 |
$commentdataoffset = 0;
|
537 |
$VorbisCommentPage = 1;
|
|
|
538 |
|
539 |
switch ($info['audio']['dataformat']) {
|
540 |
case 'vorbis':
|
@@ -581,7 +634,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
581 |
|
582 |
if ($i >= 10000) {
|
583 |
// https://github.com/owncloud/music/issues/212#issuecomment-43082336
|
584 |
-
$
|
585 |
break;
|
586 |
}
|
587 |
|
@@ -619,7 +672,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
619 |
$commentdataoffset += 4;
|
620 |
while ((strlen($commentdata) - $commentdataoffset) < $ThisFileInfo_ogg_comments_raw[$i]['size']) {
|
621 |
if (($ThisFileInfo_ogg_comments_raw[$i]['size'] > $info['avdataend']) || ($ThisFileInfo_ogg_comments_raw[$i]['size'] < 0)) {
|
622 |
-
$
|
623 |
break 2;
|
624 |
}
|
625 |
|
@@ -643,12 +696,12 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
643 |
|
644 |
//$commentdata .= $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
|
645 |
if (!isset($info['ogg']['pageheader'][$VorbisCommentPage])) {
|
646 |
-
$
|
647 |
break;
|
648 |
}
|
649 |
$readlength = self::OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1);
|
650 |
if ($readlength <= 0) {
|
651 |
-
$
|
652 |
break;
|
653 |
}
|
654 |
$commentdata .= $this->fread($readlength);
|
@@ -662,7 +715,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
662 |
if (!$commentstring) {
|
663 |
|
664 |
// no comment?
|
665 |
-
$
|
666 |
|
667 |
} elseif (strstr($commentstring, '=')) {
|
668 |
|
@@ -712,7 +765,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
712 |
|
713 |
} else {
|
714 |
|
715 |
-
$
|
716 |
|
717 |
}
|
718 |
unset($ThisFileInfo_ogg_comments_raw[$i]);
|
@@ -765,6 +818,11 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
765 |
return true;
|
766 |
}
|
767 |
|
|
|
|
|
|
|
|
|
|
|
768 |
public static function SpeexBandModeLookup($mode) {
|
769 |
static $SpeexBandModeLookup = array();
|
770 |
if (empty($SpeexBandModeLookup)) {
|
@@ -775,8 +833,14 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
775 |
return (isset($SpeexBandModeLookup[$mode]) ? $SpeexBandModeLookup[$mode] : null);
|
776 |
}
|
777 |
|
778 |
-
|
|
|
|
|
|
|
|
|
|
|
779 |
public static function OggPageSegmentLength($OggInfoArray, $SegmentNumber=1) {
|
|
|
780 |
for ($i = 0; $i < $SegmentNumber; $i++) {
|
781 |
$segmentlength = 0;
|
782 |
foreach ($OggInfoArray['segment_table'] as $key => $value) {
|
@@ -789,7 +853,11 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
789 |
return $segmentlength;
|
790 |
}
|
791 |
|
792 |
-
|
|
|
|
|
|
|
|
|
793 |
public static function get_quality_from_nominal_bitrate($nominal_bitrate) {
|
794 |
|
795 |
// decrease precision
|
@@ -813,6 +881,11 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
813 |
return round($qval, 1); // 5 or 4.9
|
814 |
}
|
815 |
|
|
|
|
|
|
|
|
|
|
|
816 |
public static function TheoraColorSpace($colorspace_id) {
|
817 |
// http://www.theora.org/doc/Theora.pdf (table 6.3)
|
818 |
static $TheoraColorSpaceLookup = array();
|
@@ -825,6 +898,11 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
|
825 |
return (isset($TheoraColorSpaceLookup[$colorspace_id]) ? $TheoraColorSpaceLookup[$colorspace_id] : null);
|
826 |
}
|
827 |
|
|
|
|
|
|
|
|
|
|
|
828 |
public static function TheoraPixelFormat($pixelformat_id) {
|
829 |
// http://www.theora.org/doc/Theora.pdf (table 6.4)
|
830 |
static $TheoraPixelFormatLookup = array();
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.ogg.php //
|
18 |
|
19 |
class getid3_ogg extends getid3_handler
|
20 |
{
|
21 |
+
/**
|
22 |
+
* @link http://xiph.org/vorbis/doc/Vorbis_I_spec.html
|
23 |
+
*
|
24 |
+
* @return bool
|
25 |
+
*/
|
26 |
public function Analyze() {
|
27 |
$info = &$this->getid3->info;
|
28 |
|
30 |
|
31 |
// Warn about illegal tags - only vorbiscomments are allowed
|
32 |
if (isset($info['id3v2'])) {
|
33 |
+
$this->warning('Illegal ID3v2 tag present.');
|
34 |
}
|
35 |
if (isset($info['id3v1'])) {
|
36 |
+
$this->warning('Illegal ID3v1 tag present.');
|
37 |
}
|
38 |
if (isset($info['ape'])) {
|
39 |
+
$this->warning('Illegal APE tag present.');
|
40 |
}
|
41 |
|
42 |
|
48 |
$info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
|
49 |
|
50 |
if ($this->ftell() >= $this->getid3->fread_buffer_size()) {
|
51 |
+
$this->error('Could not find start of Ogg page in the first '.$this->getid3->fread_buffer_size().' bytes (this might not be an Ogg-Vorbis file?)');
|
52 |
unset($info['fileformat']);
|
53 |
unset($info['ogg']);
|
54 |
return false;
|
69 |
|
70 |
} elseif (substr($filedata, 0, 8) == 'OpusHead') {
|
71 |
|
72 |
+
if ($this->ParseOpusPageHeader($filedata, $filedataoffset, $oggpageinfo) === false) {
|
73 |
return false;
|
74 |
}
|
75 |
|
183 |
if ($info['ogg']['pageheader']['theora']['pixel_aspect_denominator'] > 0) {
|
184 |
$info['video']['pixel_aspect_ratio'] = (float) $info['ogg']['pageheader']['theora']['pixel_aspect_numerator'] / $info['ogg']['pageheader']['theora']['pixel_aspect_denominator'];
|
185 |
}
|
186 |
+
$this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['.$this->getid3->version().'] -- bitrate, playtime and all audio data are currently unavailable');
|
187 |
|
188 |
|
189 |
} elseif (substr($filedata, 0, 8) == "fishead\x00") {
|
244 |
} elseif (substr($filedata, 1, 6) == 'theora') {
|
245 |
|
246 |
$info['video']['dataformat'] = 'theora1';
|
247 |
+
$this->error('Ogg Theora (v1) not correctly handled in this version of getID3 ['.$this->getid3->version().']');
|
248 |
//break;
|
249 |
|
250 |
} elseif (substr($filedata, 1, 6) == 'vorbis') {
|
252 |
$this->ParseVorbisPageHeader($filedata, $filedataoffset, $oggpageinfo);
|
253 |
|
254 |
} else {
|
255 |
+
$this->error('unexpected');
|
256 |
//break;
|
257 |
}
|
258 |
//} while ($oggpageinfo['page_seqno'] == 0);
|
260 |
|
261 |
$this->fseek($oggpageinfo['page_start_offset']);
|
262 |
|
263 |
+
$this->error('Ogg Skeleton not correctly handled in this version of getID3 ['.$this->getid3->version().']');
|
264 |
//return false;
|
265 |
|
266 |
+
} elseif (substr($filedata, 0, 5) == "\x7F".'FLAC') {
|
267 |
+
// https://xiph.org/flac/ogg_mapping.html
|
268 |
+
|
269 |
+
$info['audio']['dataformat'] = 'flac';
|
270 |
+
$info['audio']['bitrate_mode'] = 'vbr';
|
271 |
+
$info['audio']['lossless'] = true;
|
272 |
+
|
273 |
+
$info['ogg']['flac']['header']['version_major'] = ord(substr($filedata, 5, 1));
|
274 |
+
$info['ogg']['flac']['header']['version_minor'] = ord(substr($filedata, 6, 1));
|
275 |
+
$info['ogg']['flac']['header']['header_packets'] = getid3_lib::BigEndian2Int(substr($filedata, 7, 2)) + 1; // "A two-byte, big-endian binary number signifying the number of header (non-audio) packets, not including this one. This number may be zero (0x0000) to signify 'unknown' but be aware that some decoders may not be able to handle such streams."
|
276 |
+
$info['ogg']['flac']['header']['magic'] = substr($filedata, 9, 4);
|
277 |
+
if ($info['ogg']['flac']['header']['magic'] != 'fLaC') {
|
278 |
+
$this->error('Ogg-FLAC expecting "fLaC", found "'.$info['ogg']['flac']['header']['magic'].'" ('.trim(getid3_lib::PrintHexBytes($info['ogg']['flac']['header']['magic'])).')');
|
279 |
+
return false;
|
280 |
+
}
|
281 |
+
$info['ogg']['flac']['header']['STREAMINFO_bytes'] = getid3_lib::BigEndian2Int(substr($filedata, 13, 4));
|
282 |
+
$info['flac']['STREAMINFO'] = getid3_flac::parseSTREAMINFOdata(substr($filedata, 17, 34));
|
283 |
+
if (!empty($info['flac']['STREAMINFO']['sample_rate'])) {
|
284 |
+
$info['audio']['bitrate_mode'] = 'vbr';
|
285 |
+
$info['audio']['sample_rate'] = $info['flac']['STREAMINFO']['sample_rate'];
|
286 |
+
$info['audio']['channels'] = $info['flac']['STREAMINFO']['channels'];
|
287 |
+
$info['audio']['bits_per_sample'] = $info['flac']['STREAMINFO']['bits_per_sample'];
|
288 |
+
$info['playtime_seconds'] = $info['flac']['STREAMINFO']['samples_stream'] / $info['flac']['STREAMINFO']['sample_rate'];
|
289 |
+
}
|
290 |
+
|
291 |
} else {
|
292 |
|
293 |
+
$this->error('Expecting one of "vorbis", "Speex", "OpusHead", "vorbis", "fishhead", "theora", "fLaC" identifier strings, found "'.substr($filedata, 0, 8).'"');
|
294 |
unset($info['ogg']);
|
295 |
unset($info['mime_type']);
|
296 |
return false;
|
313 |
case 'flac':
|
314 |
$flac = new getid3_flac($this->getid3);
|
315 |
if (!$flac->parseMETAdata()) {
|
316 |
+
$this->error('Failed to parse FLAC headers');
|
317 |
return false;
|
318 |
}
|
319 |
unset($flac);
|
328 |
$filedata = $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
|
329 |
$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] = substr($filedata, 0, 8); // hard-coded to 'OpusTags'
|
330 |
if(substr($filedata, 0, 8) != 'OpusTags') {
|
331 |
+
$this->error('Expected "OpusTags" as header but got "'.substr($filedata, 0, 8).'"');
|
332 |
return false;
|
333 |
}
|
334 |
|
340 |
// Last Page - Number of Samples
|
341 |
if (!getid3_lib::intValueSupported($info['avdataend'])) {
|
342 |
|
343 |
+
$this->warning('Unable to parse Ogg end chunk file (PHP does not support file operations beyond '.round(PHP_INT_MAX / 1073741824).'GB)');
|
344 |
|
345 |
} else {
|
346 |
|
352 |
$info['ogg']['pageheader']['eos'] = $this->ParseOggPageHeader();
|
353 |
$info['ogg']['samples'] = $info['ogg']['pageheader']['eos']['pcm_abs_position'];
|
354 |
if ($info['ogg']['samples'] == 0) {
|
355 |
+
$this->error('Corrupt Ogg file: eos.number of samples == zero');
|
356 |
return false;
|
357 |
}
|
358 |
if (!empty($info['audio']['sample_rate'])) {
|
371 |
}
|
372 |
if (isset($info['audio']['bitrate']) && !isset($info['playtime_seconds'])) {
|
373 |
if ($info['audio']['bitrate'] == 0) {
|
374 |
+
$this->error('Corrupt Ogg file: bitrate_audio == zero');
|
375 |
return false;
|
376 |
}
|
377 |
$info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $info['audio']['bitrate']);
|
407 |
return true;
|
408 |
}
|
409 |
|
410 |
+
/**
|
411 |
+
* @param string $filedata
|
412 |
+
* @param int $filedataoffset
|
413 |
+
* @param array $oggpageinfo
|
414 |
+
*
|
415 |
+
* @return bool
|
416 |
+
*/
|
417 |
public function ParseVorbisPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo) {
|
418 |
$info = &$this->getid3->info;
|
419 |
$info['audio']['dataformat'] = 'vorbis';
|
431 |
$info['ogg']['samplerate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
432 |
$filedataoffset += 4;
|
433 |
if ($info['ogg']['samplerate'] == 0) {
|
434 |
+
$this->error('Corrupt Ogg file: sample rate == zero');
|
435 |
return false;
|
436 |
}
|
437 |
$info['audio']['sample_rate'] = $info['ogg']['samplerate'];
|
462 |
return true;
|
463 |
}
|
464 |
|
465 |
+
/**
|
466 |
+
* @link http://tools.ietf.org/html/draft-ietf-codec-oggopus-03
|
467 |
+
*
|
468 |
+
* @param string $filedata
|
469 |
+
* @param int $filedataoffset
|
470 |
+
* @param array $oggpageinfo
|
471 |
+
*
|
472 |
+
* @return bool
|
473 |
+
*/
|
474 |
public function ParseOpusPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo) {
|
475 |
$info = &$this->getid3->info;
|
476 |
$info['audio']['dataformat'] = 'opus';
|
487 |
$filedataoffset += 1;
|
488 |
|
489 |
if ($info['ogg']['pageheader']['opus']['version'] < 1 || $info['ogg']['pageheader']['opus']['version'] > 15) {
|
490 |
+
$this->error('Unknown opus version number (only accepting 1-15)');
|
491 |
return false;
|
492 |
}
|
493 |
|
495 |
$filedataoffset += 1;
|
496 |
|
497 |
if ($info['ogg']['pageheader']['opus']['out_channel_count'] == 0) {
|
498 |
+
$this->error('Invalid channel count in opus header (must not be zero)');
|
499 |
return false;
|
500 |
}
|
501 |
|
502 |
$info['ogg']['pageheader']['opus']['pre_skip'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2));
|
503 |
$filedataoffset += 2;
|
504 |
|
505 |
+
$info['ogg']['pageheader']['opus']['input_sample_rate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
|
506 |
$filedataoffset += 4;
|
507 |
|
508 |
//$info['ogg']['pageheader']['opus']['output_gain'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2));
|
511 |
//$info['ogg']['pageheader']['opus']['channel_mapping_family'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1));
|
512 |
//$filedataoffset += 1;
|
513 |
|
514 |
+
$info['opus']['opus_version'] = $info['ogg']['pageheader']['opus']['version'];
|
515 |
+
$info['opus']['sample_rate_input'] = $info['ogg']['pageheader']['opus']['input_sample_rate'];
|
516 |
+
$info['opus']['out_channel_count'] = $info['ogg']['pageheader']['opus']['out_channel_count'];
|
517 |
|
518 |
+
$info['audio']['channels'] = $info['opus']['out_channel_count'];
|
519 |
+
$info['audio']['sample_rate_input'] = $info['opus']['sample_rate_input'];
|
520 |
+
$info['audio']['sample_rate'] = 48000; // "All Opus audio is coded at 48 kHz, and should also be decoded at 48 kHz for playback (unless the target hardware does not support this sampling rate). However, this field may be used to resample the audio back to the original sampling rate, for example, when saving the output to a file." -- https://mf4.xiph.org/jenkins/view/opus/job/opusfile-unix/ws/doc/html/structOpusHead.html
|
521 |
return true;
|
522 |
}
|
523 |
|
524 |
+
/**
|
525 |
+
* @return array|false
|
526 |
+
*/
|
527 |
public function ParseOggPageHeader() {
|
528 |
// http://xiph.org/ogg/vorbis/doc/framing.html
|
529 |
$oggheader['page_start_offset'] = $this->ftell(); // where we started from in the file
|
536 |
return false;
|
537 |
}
|
538 |
if ((($filedataoffset + 28) > strlen($filedata)) || (strlen($filedata) < 28)) {
|
539 |
+
if ($this->feof() || (($filedata .= $this->fread($this->getid3->fread_buffer_size())) === '')) {
|
540 |
// get some more data, unless eof, in which case fail
|
541 |
return false;
|
542 |
}
|
575 |
return $oggheader;
|
576 |
}
|
577 |
|
578 |
+
/**
|
579 |
+
* @link http://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810005
|
580 |
+
*
|
581 |
+
* @return bool
|
582 |
+
*/
|
583 |
public function ParseVorbisComments() {
|
584 |
$info = &$this->getid3->info;
|
585 |
|
586 |
$OriginalOffset = $this->ftell();
|
587 |
+
$commentdata = null;
|
588 |
$commentdataoffset = 0;
|
589 |
$VorbisCommentPage = 1;
|
590 |
+
$CommentStartOffset = 0;
|
591 |
|
592 |
switch ($info['audio']['dataformat']) {
|
593 |
case 'vorbis':
|
634 |
|
635 |
if ($i >= 10000) {
|
636 |
// https://github.com/owncloud/music/issues/212#issuecomment-43082336
|
637 |
+
$this->warning('Unexpectedly large number ('.$CommentsCount.') of Ogg comments - breaking after reading '.$i.' comments');
|
638 |
break;
|
639 |
}
|
640 |
|
672 |
$commentdataoffset += 4;
|
673 |
while ((strlen($commentdata) - $commentdataoffset) < $ThisFileInfo_ogg_comments_raw[$i]['size']) {
|
674 |
if (($ThisFileInfo_ogg_comments_raw[$i]['size'] > $info['avdataend']) || ($ThisFileInfo_ogg_comments_raw[$i]['size'] < 0)) {
|
675 |
+
$this->warning('Invalid Ogg comment size (comment #'.$i.', claims to be '.number_format($ThisFileInfo_ogg_comments_raw[$i]['size']).' bytes) - aborting reading comments');
|
676 |
break 2;
|
677 |
}
|
678 |
|
696 |
|
697 |
//$commentdata .= $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
|
698 |
if (!isset($info['ogg']['pageheader'][$VorbisCommentPage])) {
|
699 |
+
$this->warning('undefined Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell());
|
700 |
break;
|
701 |
}
|
702 |
$readlength = self::OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1);
|
703 |
if ($readlength <= 0) {
|
704 |
+
$this->warning('invalid length Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell());
|
705 |
break;
|
706 |
}
|
707 |
$commentdata .= $this->fread($readlength);
|
715 |
if (!$commentstring) {
|
716 |
|
717 |
// no comment?
|
718 |
+
$this->warning('Blank Ogg comment ['.$i.']');
|
719 |
|
720 |
} elseif (strstr($commentstring, '=')) {
|
721 |
|
765 |
|
766 |
} else {
|
767 |
|
768 |
+
$this->warning('[known problem with CDex >= v1.40, < v1.50b7] Invalid Ogg comment name/value pair ['.$i.']: '.$commentstring);
|
769 |
|
770 |
}
|
771 |
unset($ThisFileInfo_ogg_comments_raw[$i]);
|
818 |
return true;
|
819 |
}
|
820 |
|
821 |
+
/**
|
822 |
+
* @param int $mode
|
823 |
+
*
|
824 |
+
* @return string|null
|
825 |
+
*/
|
826 |
public static function SpeexBandModeLookup($mode) {
|
827 |
static $SpeexBandModeLookup = array();
|
828 |
if (empty($SpeexBandModeLookup)) {
|
833 |
return (isset($SpeexBandModeLookup[$mode]) ? $SpeexBandModeLookup[$mode] : null);
|
834 |
}
|
835 |
|
836 |
+
/**
|
837 |
+
* @param array $OggInfoArray
|
838 |
+
* @param int $SegmentNumber
|
839 |
+
*
|
840 |
+
* @return int
|
841 |
+
*/
|
842 |
public static function OggPageSegmentLength($OggInfoArray, $SegmentNumber=1) {
|
843 |
+
$segmentlength = 0;
|
844 |
for ($i = 0; $i < $SegmentNumber; $i++) {
|
845 |
$segmentlength = 0;
|
846 |
foreach ($OggInfoArray['segment_table'] as $key => $value) {
|
853 |
return $segmentlength;
|
854 |
}
|
855 |
|
856 |
+
/**
|
857 |
+
* @param int $nominal_bitrate
|
858 |
+
*
|
859 |
+
* @return float
|
860 |
+
*/
|
861 |
public static function get_quality_from_nominal_bitrate($nominal_bitrate) {
|
862 |
|
863 |
// decrease precision
|
881 |
return round($qval, 1); // 5 or 4.9
|
882 |
}
|
883 |
|
884 |
+
/**
|
885 |
+
* @param int $colorspace_id
|
886 |
+
*
|
887 |
+
* @return string|null
|
888 |
+
*/
|
889 |
public static function TheoraColorSpace($colorspace_id) {
|
890 |
// http://www.theora.org/doc/Theora.pdf (table 6.3)
|
891 |
static $TheoraColorSpaceLookup = array();
|
898 |
return (isset($TheoraColorSpaceLookup[$colorspace_id]) ? $TheoraColorSpaceLookup[$colorspace_id] : null);
|
899 |
}
|
900 |
|
901 |
+
/**
|
902 |
+
* @param int $pixelformat_id
|
903 |
+
*
|
904 |
+
* @return string|null
|
905 |
+
*/
|
906 |
public static function TheoraPixelFormat($pixelformat_id) {
|
907 |
// http://www.theora.org/doc/Theora.pdf (table 6.4)
|
908 |
static $TheoraPixelFormatLookup = array();
|
lib/getid3/module.audio.optimfrog.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.optimfrog.php //
|
@@ -18,7 +18,9 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php',
|
|
18 |
|
19 |
class getid3_optimfrog extends getid3_handler
|
20 |
{
|
21 |
-
|
|
|
|
|
22 |
public function Analyze() {
|
23 |
$info = &$this->getid3->info;
|
24 |
|
@@ -39,12 +41,14 @@ class getid3_optimfrog extends getid3_handler
|
|
39 |
|
40 |
}
|
41 |
|
42 |
-
$
|
43 |
unset($info['fileformat']);
|
44 |
return false;
|
45 |
}
|
46 |
|
47 |
-
|
|
|
|
|
48 |
public function ParseOptimFROGheader42() {
|
49 |
// for fileformat of v4.21 and older
|
50 |
|
@@ -91,7 +95,9 @@ class getid3_optimfrog extends getid3_handler
|
|
91 |
return true;
|
92 |
}
|
93 |
|
94 |
-
|
|
|
|
|
95 |
public function ParseOptimFROGheader45() {
|
96 |
// for fileformat of v4.50a and higher
|
97 |
|
@@ -128,7 +134,7 @@ class getid3_optimfrog extends getid3_handler
|
|
128 |
break;
|
129 |
|
130 |
default:
|
131 |
-
$
|
132 |
break;
|
133 |
}
|
134 |
$BlockData .= $this->fread($BlockSize);
|
@@ -252,7 +258,7 @@ class getid3_optimfrog extends getid3_handler
|
|
252 |
|
253 |
$thisfile_ofr_thisblock['offset'] = $BlockOffset;
|
254 |
$thisfile_ofr_thisblock['size'] = $BlockSize;
|
255 |
-
$
|
256 |
|
257 |
$this->fseek($BlockSize, SEEK_CUR);
|
258 |
break;
|
@@ -272,7 +278,7 @@ class getid3_optimfrog extends getid3_handler
|
|
272 |
|
273 |
} else {
|
274 |
|
275 |
-
$
|
276 |
$this->fseek($BlockSize, SEEK_CUR);
|
277 |
|
278 |
}
|
@@ -283,7 +289,7 @@ class getid3_optimfrog extends getid3_handler
|
|
283 |
$thisfile_ofr_thisblock['offset'] = $BlockOffset;
|
284 |
$thisfile_ofr_thisblock['size'] = $BlockSize;
|
285 |
|
286 |
-
$
|
287 |
$this->fseek($BlockSize, SEEK_CUR);
|
288 |
break;
|
289 |
}
|
@@ -313,7 +319,11 @@ class getid3_optimfrog extends getid3_handler
|
|
313 |
return true;
|
314 |
}
|
315 |
|
316 |
-
|
|
|
|
|
|
|
|
|
317 |
public static function OptimFROGsampleTypeLookup($SampleType) {
|
318 |
static $OptimFROGsampleTypeLookup = array(
|
319 |
0 => 'unsigned int (8-bit)',
|
@@ -331,6 +341,11 @@ class getid3_optimfrog extends getid3_handler
|
|
331 |
return (isset($OptimFROGsampleTypeLookup[$SampleType]) ? $OptimFROGsampleTypeLookup[$SampleType] : false);
|
332 |
}
|
333 |
|
|
|
|
|
|
|
|
|
|
|
334 |
public static function OptimFROGbitsPerSampleTypeLookup($SampleType) {
|
335 |
static $OptimFROGbitsPerSampleTypeLookup = array(
|
336 |
0 => 8,
|
@@ -348,6 +363,11 @@ class getid3_optimfrog extends getid3_handler
|
|
348 |
return (isset($OptimFROGbitsPerSampleTypeLookup[$SampleType]) ? $OptimFROGbitsPerSampleTypeLookup[$SampleType] : false);
|
349 |
}
|
350 |
|
|
|
|
|
|
|
|
|
|
|
351 |
public static function OptimFROGchannelConfigurationLookup($ChannelConfiguration) {
|
352 |
static $OptimFROGchannelConfigurationLookup = array(
|
353 |
0 => 'mono',
|
@@ -356,6 +376,11 @@ class getid3_optimfrog extends getid3_handler
|
|
356 |
return (isset($OptimFROGchannelConfigurationLookup[$ChannelConfiguration]) ? $OptimFROGchannelConfigurationLookup[$ChannelConfiguration] : false);
|
357 |
}
|
358 |
|
|
|
|
|
|
|
|
|
|
|
359 |
public static function OptimFROGchannelConfigNumChannelsLookup($ChannelConfiguration) {
|
360 |
static $OptimFROGchannelConfigNumChannelsLookup = array(
|
361 |
0 => 1,
|
@@ -365,13 +390,17 @@ class getid3_optimfrog extends getid3_handler
|
|
365 |
}
|
366 |
|
367 |
|
368 |
-
|
369 |
// static function OptimFROGalgorithmNameLookup($AlgorithID) {
|
370 |
// static $OptimFROGalgorithmNameLookup = array();
|
371 |
// return (isset($OptimFROGalgorithmNameLookup[$AlgorithID]) ? $OptimFROGalgorithmNameLookup[$AlgorithID] : false);
|
372 |
// }
|
373 |
|
374 |
|
|
|
|
|
|
|
|
|
|
|
375 |
public static function OptimFROGencoderNameLookup($EncoderID) {
|
376 |
// version = (encoderID >> 4) + 4500
|
377 |
// system = encoderID & 0xF
|
@@ -387,6 +416,11 @@ class getid3_optimfrog extends getid3_handler
|
|
387 |
return $EncoderVersion.' ('.(isset($OptimFROGencoderSystemLookup[$EncoderSystemID]) ? $OptimFROGencoderSystemLookup[$EncoderSystemID] : 'undefined encoder type (0x'.dechex($EncoderSystemID).')').')';
|
388 |
}
|
389 |
|
|
|
|
|
|
|
|
|
|
|
390 |
public static function OptimFROGcompressionLookup($CompressionID) {
|
391 |
// mode = compression >> 3
|
392 |
// speedup = compression & 0x07
|
@@ -409,6 +443,11 @@ class getid3_optimfrog extends getid3_handler
|
|
409 |
return (isset($OptimFROGencoderModeLookup[$CompressionModeID]) ? $OptimFROGencoderModeLookup[$CompressionModeID] : 'undefined mode (0x'.str_pad(dechex($CompressionModeID), 2, '0', STR_PAD_LEFT).')');
|
410 |
}
|
411 |
|
|
|
|
|
|
|
|
|
|
|
412 |
public static function OptimFROGspeedupLookup($CompressionID) {
|
413 |
// mode = compression >> 3
|
414 |
// speedup = compression & 0x07
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.optimfrog.php //
|
18 |
|
19 |
class getid3_optimfrog extends getid3_handler
|
20 |
{
|
21 |
+
/**
|
22 |
+
* @return bool
|
23 |
+
*/
|
24 |
public function Analyze() {
|
25 |
$info = &$this->getid3->info;
|
26 |
|
41 |
|
42 |
}
|
43 |
|
44 |
+
$this->error('Expecting "*RIFF" or "OFR " at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($OFRheader).'"');
|
45 |
unset($info['fileformat']);
|
46 |
return false;
|
47 |
}
|
48 |
|
49 |
+
/**
|
50 |
+
* @return bool
|
51 |
+
*/
|
52 |
public function ParseOptimFROGheader42() {
|
53 |
// for fileformat of v4.21 and older
|
54 |
|
95 |
return true;
|
96 |
}
|
97 |
|
98 |
+
/**
|
99 |
+
* @return bool
|
100 |
+
*/
|
101 |
public function ParseOptimFROGheader45() {
|
102 |
// for fileformat of v4.50a and higher
|
103 |
|
134 |
break;
|
135 |
|
136 |
default:
|
137 |
+
$this->warning('"'.$BlockName.'" contains more data than expected (expected 12 or 15 bytes, found '.$BlockSize.' bytes)');
|
138 |
break;
|
139 |
}
|
140 |
$BlockData .= $this->fread($BlockSize);
|
258 |
|
259 |
$thisfile_ofr_thisblock['offset'] = $BlockOffset;
|
260 |
$thisfile_ofr_thisblock['size'] = $BlockSize;
|
261 |
+
$this->warning('APEtag processing inside OptimFROG not supported in this version ('.$this->getid3->version().') of getID3()');
|
262 |
|
263 |
$this->fseek($BlockSize, SEEK_CUR);
|
264 |
break;
|
278 |
|
279 |
} else {
|
280 |
|
281 |
+
$this->warning('Expecting block size of 16 in "MD5 " chunk, found '.$BlockSize.' instead');
|
282 |
$this->fseek($BlockSize, SEEK_CUR);
|
283 |
|
284 |
}
|
289 |
$thisfile_ofr_thisblock['offset'] = $BlockOffset;
|
290 |
$thisfile_ofr_thisblock['size'] = $BlockSize;
|
291 |
|
292 |
+
$this->warning('Unhandled OptimFROG block type "'.$BlockName.'" at offset '.$thisfile_ofr_thisblock['offset']);
|
293 |
$this->fseek($BlockSize, SEEK_CUR);
|
294 |
break;
|
295 |
}
|
319 |
return true;
|
320 |
}
|
321 |
|
322 |
+
/**
|
323 |
+
* @param int $SampleType
|
324 |
+
*
|
325 |
+
* @return string|false
|
326 |
+
*/
|
327 |
public static function OptimFROGsampleTypeLookup($SampleType) {
|
328 |
static $OptimFROGsampleTypeLookup = array(
|
329 |
0 => 'unsigned int (8-bit)',
|
341 |
return (isset($OptimFROGsampleTypeLookup[$SampleType]) ? $OptimFROGsampleTypeLookup[$SampleType] : false);
|
342 |
}
|
343 |
|
344 |
+
/**
|
345 |
+
* @param int $SampleType
|
346 |
+
*
|
347 |
+
* @return int|false
|
348 |
+
*/
|
349 |
public static function OptimFROGbitsPerSampleTypeLookup($SampleType) {
|
350 |
static $OptimFROGbitsPerSampleTypeLookup = array(
|
351 |
0 => 8,
|
363 |
return (isset($OptimFROGbitsPerSampleTypeLookup[$SampleType]) ? $OptimFROGbitsPerSampleTypeLookup[$SampleType] : false);
|
364 |
}
|
365 |
|
366 |
+
/**
|
367 |
+
* @param int $ChannelConfiguration
|
368 |
+
*
|
369 |
+
* @return string|false
|
370 |
+
*/
|
371 |
public static function OptimFROGchannelConfigurationLookup($ChannelConfiguration) {
|
372 |
static $OptimFROGchannelConfigurationLookup = array(
|
373 |
0 => 'mono',
|
376 |
return (isset($OptimFROGchannelConfigurationLookup[$ChannelConfiguration]) ? $OptimFROGchannelConfigurationLookup[$ChannelConfiguration] : false);
|
377 |
}
|
378 |
|
379 |
+
/**
|
380 |
+
* @param int $ChannelConfiguration
|
381 |
+
*
|
382 |
+
* @return int|false
|
383 |
+
*/
|
384 |
public static function OptimFROGchannelConfigNumChannelsLookup($ChannelConfiguration) {
|
385 |
static $OptimFROGchannelConfigNumChannelsLookup = array(
|
386 |
0 => 1,
|
390 |
}
|
391 |
|
392 |
|
|
|
393 |
// static function OptimFROGalgorithmNameLookup($AlgorithID) {
|
394 |
// static $OptimFROGalgorithmNameLookup = array();
|
395 |
// return (isset($OptimFROGalgorithmNameLookup[$AlgorithID]) ? $OptimFROGalgorithmNameLookup[$AlgorithID] : false);
|
396 |
// }
|
397 |
|
398 |
|
399 |
+
/**
|
400 |
+
* @param int $EncoderID
|
401 |
+
*
|
402 |
+
* @return string
|
403 |
+
*/
|
404 |
public static function OptimFROGencoderNameLookup($EncoderID) {
|
405 |
// version = (encoderID >> 4) + 4500
|
406 |
// system = encoderID & 0xF
|
416 |
return $EncoderVersion.' ('.(isset($OptimFROGencoderSystemLookup[$EncoderSystemID]) ? $OptimFROGencoderSystemLookup[$EncoderSystemID] : 'undefined encoder type (0x'.dechex($EncoderSystemID).')').')';
|
417 |
}
|
418 |
|
419 |
+
/**
|
420 |
+
* @param int $CompressionID
|
421 |
+
*
|
422 |
+
* @return string
|
423 |
+
*/
|
424 |
public static function OptimFROGcompressionLookup($CompressionID) {
|
425 |
// mode = compression >> 3
|
426 |
// speedup = compression & 0x07
|
443 |
return (isset($OptimFROGencoderModeLookup[$CompressionModeID]) ? $OptimFROGencoderModeLookup[$CompressionModeID] : 'undefined mode (0x'.str_pad(dechex($CompressionModeID), 2, '0', STR_PAD_LEFT).')');
|
444 |
}
|
445 |
|
446 |
+
/**
|
447 |
+
* @param int $CompressionID
|
448 |
+
*
|
449 |
+
* @return string
|
450 |
+
*/
|
451 |
public static function OptimFROGspeedupLookup($CompressionID) {
|
452 |
// mode = compression >> 3
|
453 |
// speedup = compression & 0x07
|
lib/getid3/module.audio.rkau.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.shorten.php //
|
@@ -17,7 +17,9 @@
|
|
17 |
|
18 |
class getid3_rkau extends getid3_handler
|
19 |
{
|
20 |
-
|
|
|
|
|
21 |
public function Analyze() {
|
22 |
$info = &$this->getid3->info;
|
23 |
|
@@ -25,7 +27,7 @@ class getid3_rkau extends getid3_handler
|
|
25 |
$RKAUHeader = $this->fread(20);
|
26 |
$magic = 'RKA';
|
27 |
if (substr($RKAUHeader, 0, 3) != $magic) {
|
28 |
-
$
|
29 |
return false;
|
30 |
}
|
31 |
|
@@ -36,7 +38,7 @@ class getid3_rkau extends getid3_handler
|
|
36 |
$info['rkau']['raw']['version'] = getid3_lib::LittleEndian2Int(substr($RKAUHeader, 3, 1));
|
37 |
$info['rkau']['version'] = '1.'.str_pad($info['rkau']['raw']['version'] & 0x0F, 2, '0', STR_PAD_LEFT);
|
38 |
if (($info['rkau']['version'] > 1.07) || ($info['rkau']['version'] < 1.06)) {
|
39 |
-
$
|
40 |
unset($info['rkau']);
|
41 |
return false;
|
42 |
}
|
@@ -50,7 +52,7 @@ class getid3_rkau extends getid3_handler
|
|
50 |
$this->RKAUqualityLookup($info['rkau']);
|
51 |
|
52 |
$info['rkau']['raw']['flags'] = getid3_lib::LittleEndian2Int(substr($RKAUHeader, 15, 1));
|
53 |
-
$info['rkau']['flags']['joint_stereo'] =
|
54 |
$info['rkau']['flags']['streaming'] = (bool) ($info['rkau']['raw']['flags'] & 0x02);
|
55 |
$info['rkau']['flags']['vrq_lossy_mode'] = (bool) ($info['rkau']['raw']['flags'] & 0x04);
|
56 |
|
@@ -76,7 +78,11 @@ class getid3_rkau extends getid3_handler
|
|
76 |
|
77 |
}
|
78 |
|
79 |
-
|
|
|
|
|
|
|
|
|
80 |
public function RKAUqualityLookup(&$RKAUdata) {
|
81 |
$level = ($RKAUdata['raw']['quality'] & 0xF0) >> 4;
|
82 |
$quality = $RKAUdata['raw']['quality'] & 0x0F;
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.shorten.php //
|
17 |
|
18 |
class getid3_rkau extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @return bool
|
22 |
+
*/
|
23 |
public function Analyze() {
|
24 |
$info = &$this->getid3->info;
|
25 |
|
27 |
$RKAUHeader = $this->fread(20);
|
28 |
$magic = 'RKA';
|
29 |
if (substr($RKAUHeader, 0, 3) != $magic) {
|
30 |
+
$this->error('Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($RKAUHeader, 0, 3)).'"');
|
31 |
return false;
|
32 |
}
|
33 |
|
38 |
$info['rkau']['raw']['version'] = getid3_lib::LittleEndian2Int(substr($RKAUHeader, 3, 1));
|
39 |
$info['rkau']['version'] = '1.'.str_pad($info['rkau']['raw']['version'] & 0x0F, 2, '0', STR_PAD_LEFT);
|
40 |
if (($info['rkau']['version'] > 1.07) || ($info['rkau']['version'] < 1.06)) {
|
41 |
+
$this->error('This version of getID3() ['.$this->getid3->version().'] can only parse RKAU files v1.06 and 1.07 (this file is v'.$info['rkau']['version'].')');
|
42 |
unset($info['rkau']);
|
43 |
return false;
|
44 |
}
|
52 |
$this->RKAUqualityLookup($info['rkau']);
|
53 |
|
54 |
$info['rkau']['raw']['flags'] = getid3_lib::LittleEndian2Int(substr($RKAUHeader, 15, 1));
|
55 |
+
$info['rkau']['flags']['joint_stereo'] = !($info['rkau']['raw']['flags'] & 0x01);
|
56 |
$info['rkau']['flags']['streaming'] = (bool) ($info['rkau']['raw']['flags'] & 0x02);
|
57 |
$info['rkau']['flags']['vrq_lossy_mode'] = (bool) ($info['rkau']['raw']['flags'] & 0x04);
|
58 |
|
78 |
|
79 |
}
|
80 |
|
81 |
+
/**
|
82 |
+
* @param array $RKAUdata
|
83 |
+
*
|
84 |
+
* @return bool
|
85 |
+
*/
|
86 |
public function RKAUqualityLookup(&$RKAUdata) {
|
87 |
$level = ($RKAUdata['raw']['quality'] & 0xF0) >> 4;
|
88 |
$quality = $RKAUdata['raw']['quality'] & 0x0F;
|
lib/getid3/module.audio.shorten.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.shorten.php //
|
@@ -17,7 +17,9 @@
|
|
17 |
|
18 |
class getid3_shorten extends getid3_handler
|
19 |
{
|
20 |
-
|
|
|
|
|
21 |
public function Analyze() {
|
22 |
$info = &$this->getid3->info;
|
23 |
|
@@ -26,7 +28,7 @@ class getid3_shorten extends getid3_handler
|
|
26 |
$ShortenHeader = $this->fread(8);
|
27 |
$magic = 'ajkg';
|
28 |
if (substr($ShortenHeader, 0, 4) != $magic) {
|
29 |
-
$
|
30 |
return false;
|
31 |
}
|
32 |
$info['fileformat'] = 'shn';
|
@@ -38,7 +40,7 @@ class getid3_shorten extends getid3_handler
|
|
38 |
|
39 |
$this->fseek($info['avdataend'] - 12);
|
40 |
$SeekTableSignatureTest = $this->fread(12);
|
41 |
-
$info['shn']['seektable']['present'] =
|
42 |
if ($info['shn']['seektable']['present']) {
|
43 |
$info['shn']['seektable']['length'] = getid3_lib::LittleEndian2Int(substr($SeekTableSignatureTest, 0, 4));
|
44 |
$info['shn']['seektable']['offset'] = $info['avdataend'] - $info['shn']['seektable']['length'];
|
@@ -47,7 +49,7 @@ class getid3_shorten extends getid3_handler
|
|
47 |
$magic = 'SEEK';
|
48 |
if ($SeekTableMagic != $magic) {
|
49 |
|
50 |
-
$
|
51 |
return false;
|
52 |
|
53 |
} else {
|
@@ -114,7 +116,7 @@ class getid3_shorten extends getid3_handler
|
|
114 |
}
|
115 |
|
116 |
if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) {
|
117 |
-
$
|
118 |
return false;
|
119 |
}
|
120 |
|
@@ -123,7 +125,7 @@ class getid3_shorten extends getid3_handler
|
|
123 |
$RequiredFiles = array('shorten.exe', 'cygwin1.dll', 'head.exe');
|
124 |
foreach ($RequiredFiles as $required_file) {
|
125 |
if (!is_readable(GETID3_HELPERAPPSDIR.$required_file)) {
|
126 |
-
$
|
127 |
return false;
|
128 |
}
|
129 |
}
|
@@ -137,7 +139,7 @@ class getid3_shorten extends getid3_handler
|
|
137 |
$shorten_present = file_exists('/usr/local/bin/shorten') || `which shorten`;
|
138 |
}
|
139 |
if (!$shorten_present) {
|
140 |
-
$
|
141 |
return false;
|
142 |
}
|
143 |
$commandline = (file_exists('/usr/local/bin/shorten') ? '/usr/local/bin/' : '' ) . 'shorten -x '.escapeshellarg($info['filenamepath']).' - | head -c 64';
|
@@ -162,7 +164,7 @@ class getid3_shorten extends getid3_handler
|
|
162 |
|
163 |
} else {
|
164 |
|
165 |
-
$
|
166 |
return false;
|
167 |
|
168 |
}
|
@@ -171,7 +173,7 @@ class getid3_shorten extends getid3_handler
|
|
171 |
|
172 |
} else {
|
173 |
|
174 |
-
$
|
175 |
return false;
|
176 |
|
177 |
}
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.shorten.php //
|
17 |
|
18 |
class getid3_shorten extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @return bool
|
22 |
+
*/
|
23 |
public function Analyze() {
|
24 |
$info = &$this->getid3->info;
|
25 |
|
28 |
$ShortenHeader = $this->fread(8);
|
29 |
$magic = 'ajkg';
|
30 |
if (substr($ShortenHeader, 0, 4) != $magic) {
|
31 |
+
$this->error('Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($ShortenHeader, 0, 4)).'"');
|
32 |
return false;
|
33 |
}
|
34 |
$info['fileformat'] = 'shn';
|
40 |
|
41 |
$this->fseek($info['avdataend'] - 12);
|
42 |
$SeekTableSignatureTest = $this->fread(12);
|
43 |
+
$info['shn']['seektable']['present'] = substr($SeekTableSignatureTest, 4, 8) == 'SHNAMPSK';
|
44 |
if ($info['shn']['seektable']['present']) {
|
45 |
$info['shn']['seektable']['length'] = getid3_lib::LittleEndian2Int(substr($SeekTableSignatureTest, 0, 4));
|
46 |
$info['shn']['seektable']['offset'] = $info['avdataend'] - $info['shn']['seektable']['length'];
|
49 |
$magic = 'SEEK';
|
50 |
if ($SeekTableMagic != $magic) {
|
51 |
|
52 |
+
$this->error('Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$info['shn']['seektable']['offset'].', found "'.getid3_lib::PrintHexBytes($SeekTableMagic).'"');
|
53 |
return false;
|
54 |
|
55 |
} else {
|
116 |
}
|
117 |
|
118 |
if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) {
|
119 |
+
$this->error('PHP running in Safe Mode - backtick operator not available, cannot run shntool to analyze Shorten files');
|
120 |
return false;
|
121 |
}
|
122 |
|
125 |
$RequiredFiles = array('shorten.exe', 'cygwin1.dll', 'head.exe');
|
126 |
foreach ($RequiredFiles as $required_file) {
|
127 |
if (!is_readable(GETID3_HELPERAPPSDIR.$required_file)) {
|
128 |
+
$this->error(GETID3_HELPERAPPSDIR.$required_file.' does not exist');
|
129 |
return false;
|
130 |
}
|
131 |
}
|
139 |
$shorten_present = file_exists('/usr/local/bin/shorten') || `which shorten`;
|
140 |
}
|
141 |
if (!$shorten_present) {
|
142 |
+
$this->error('shorten binary was not found in path or /usr/local/bin');
|
143 |
return false;
|
144 |
}
|
145 |
$commandline = (file_exists('/usr/local/bin/shorten') ? '/usr/local/bin/' : '' ) . 'shorten -x '.escapeshellarg($info['filenamepath']).' - | head -c 64';
|
164 |
|
165 |
} else {
|
166 |
|
167 |
+
$this->error('shorten failed to decode DATA chunk to expected location, cannot determine playtime');
|
168 |
return false;
|
169 |
|
170 |
}
|
173 |
|
174 |
} else {
|
175 |
|
176 |
+
$this->error('shorten failed to decode file to WAV for parsing');
|
177 |
return false;
|
178 |
|
179 |
}
|
lib/getid3/module.audio.tta.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.tta.php //
|
@@ -17,7 +17,9 @@
|
|
17 |
|
18 |
class getid3_tta extends getid3_handler
|
19 |
{
|
20 |
-
|
|
|
|
|
21 |
public function Analyze() {
|
22 |
$info = &$this->getid3->info;
|
23 |
|
@@ -32,7 +34,7 @@ class getid3_tta extends getid3_handler
|
|
32 |
$info['tta']['magic'] = substr($ttaheader, 0, 3);
|
33 |
$magic = 'TTA';
|
34 |
if ($info['tta']['magic'] != $magic) {
|
35 |
-
$
|
36 |
unset($info['fileformat']);
|
37 |
unset($info['audio']);
|
38 |
unset($info['tta']);
|
@@ -90,7 +92,7 @@ class getid3_tta extends getid3_handler
|
|
90 |
break;
|
91 |
|
92 |
default:
|
93 |
-
$
|
94 |
return false;
|
95 |
break;
|
96 |
}
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.tta.php //
|
17 |
|
18 |
class getid3_tta extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @return bool
|
22 |
+
*/
|
23 |
public function Analyze() {
|
24 |
$info = &$this->getid3->info;
|
25 |
|
34 |
$info['tta']['magic'] = substr($ttaheader, 0, 3);
|
35 |
$magic = 'TTA';
|
36 |
if ($info['tta']['magic'] != $magic) {
|
37 |
+
$this->error('Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($info['tta']['magic']).'"');
|
38 |
unset($info['fileformat']);
|
39 |
unset($info['audio']);
|
40 |
unset($info['tta']);
|
92 |
break;
|
93 |
|
94 |
default:
|
95 |
+
$this->error('This version of getID3() ['.$this->getid3->version().'] only knows how to handle TTA v1 and v2 - it may not work correctly with this file which appears to be TTA v'.$ttaheader{3});
|
96 |
return false;
|
97 |
break;
|
98 |
}
|
lib/getid3/module.audio.voc.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.voc.php //
|
@@ -17,7 +17,9 @@
|
|
17 |
|
18 |
class getid3_voc extends getid3_handler
|
19 |
{
|
20 |
-
|
|
|
|
|
21 |
public function Analyze() {
|
22 |
$info = &$this->getid3->info;
|
23 |
|
@@ -27,7 +29,7 @@ class getid3_voc extends getid3_handler
|
|
27 |
|
28 |
$magic = 'Creative Voice File';
|
29 |
if (substr($VOCheader, 0, 19) != $magic) {
|
30 |
-
$
|
31 |
return false;
|
32 |
}
|
33 |
|
@@ -137,7 +139,7 @@ class getid3_voc extends getid3_handler
|
|
137 |
break;
|
138 |
|
139 |
default:
|
140 |
-
$
|
141 |
$this->fseek($BlockSize, SEEK_CUR);
|
142 |
break;
|
143 |
}
|
@@ -164,6 +166,11 @@ class getid3_voc extends getid3_handler
|
|
164 |
return true;
|
165 |
}
|
166 |
|
|
|
|
|
|
|
|
|
|
|
167 |
public function VOCcompressionTypeLookup($index) {
|
168 |
static $VOCcompressionTypeLookup = array(
|
169 |
0 => '8-bit',
|
@@ -174,6 +181,11 @@ class getid3_voc extends getid3_handler
|
|
174 |
return (isset($VOCcompressionTypeLookup[$index]) ? $VOCcompressionTypeLookup[$index] : 'Multi DAC ('.($index - 3).') channels');
|
175 |
}
|
176 |
|
|
|
|
|
|
|
|
|
|
|
177 |
public function VOCwFormatLookup($index) {
|
178 |
static $VOCwFormatLookup = array(
|
179 |
0x0000 => '8-bit unsigned PCM',
|
@@ -188,6 +200,11 @@ class getid3_voc extends getid3_handler
|
|
188 |
return (isset($VOCwFormatLookup[$index]) ? $VOCwFormatLookup[$index] : false);
|
189 |
}
|
190 |
|
|
|
|
|
|
|
|
|
|
|
191 |
public function VOCwFormatActualBitsPerSampleLookup($index) {
|
192 |
static $VOCwFormatLookup = array(
|
193 |
0x0000 => 8,
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.voc.php //
|
17 |
|
18 |
class getid3_voc extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @return bool
|
22 |
+
*/
|
23 |
public function Analyze() {
|
24 |
$info = &$this->getid3->info;
|
25 |
|
29 |
|
30 |
$magic = 'Creative Voice File';
|
31 |
if (substr($VOCheader, 0, 19) != $magic) {
|
32 |
+
$this->error('Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($VOCheader, 0, 19)).'"');
|
33 |
return false;
|
34 |
}
|
35 |
|
139 |
break;
|
140 |
|
141 |
default:
|
142 |
+
$this->warning('Unhandled block type "'.$BlockType.'" at offset '.$BlockOffset);
|
143 |
$this->fseek($BlockSize, SEEK_CUR);
|
144 |
break;
|
145 |
}
|
166 |
return true;
|
167 |
}
|
168 |
|
169 |
+
/**
|
170 |
+
* @param int $index
|
171 |
+
*
|
172 |
+
* @return string
|
173 |
+
*/
|
174 |
public function VOCcompressionTypeLookup($index) {
|
175 |
static $VOCcompressionTypeLookup = array(
|
176 |
0 => '8-bit',
|
181 |
return (isset($VOCcompressionTypeLookup[$index]) ? $VOCcompressionTypeLookup[$index] : 'Multi DAC ('.($index - 3).') channels');
|
182 |
}
|
183 |
|
184 |
+
/**
|
185 |
+
* @param int $index
|
186 |
+
*
|
187 |
+
* @return string|false
|
188 |
+
*/
|
189 |
public function VOCwFormatLookup($index) {
|
190 |
static $VOCwFormatLookup = array(
|
191 |
0x0000 => '8-bit unsigned PCM',
|
200 |
return (isset($VOCwFormatLookup[$index]) ? $VOCwFormatLookup[$index] : false);
|
201 |
}
|
202 |
|
203 |
+
/**
|
204 |
+
* @param int $index
|
205 |
+
*
|
206 |
+
* @return int|false
|
207 |
+
*/
|
208 |
public function VOCwFormatActualBitsPerSampleLookup($index) {
|
209 |
static $VOCwFormatLookup = array(
|
210 |
0x0000 => 8,
|
lib/getid3/module.audio.vqf.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.vqf.php //
|
@@ -17,6 +17,9 @@
|
|
17 |
|
18 |
class getid3_vqf extends getid3_handler
|
19 |
{
|
|
|
|
|
|
|
20 |
public function Analyze() {
|
21 |
$info = &$this->getid3->info;
|
22 |
|
@@ -40,7 +43,7 @@ class getid3_vqf extends getid3_handler
|
|
40 |
$thisfile_vqf_raw['header_tag'] = substr($VQFheaderData, $offset, 4);
|
41 |
$magic = 'TWIN';
|
42 |
if ($thisfile_vqf_raw['header_tag'] != $magic) {
|
43 |
-
$
|
44 |
unset($info['vqf']);
|
45 |
unset($info['fileformat']);
|
46 |
return false;
|
@@ -65,7 +68,7 @@ class getid3_vqf extends getid3_handler
|
|
65 |
$ChunkSize = getid3_lib::BigEndian2Int(substr($ChunkData, $chunkoffset, 4));
|
66 |
$chunkoffset += 4;
|
67 |
if ($ChunkSize > ($info['avdataend'] - $this->ftell())) {
|
68 |
-
$
|
69 |
break;
|
70 |
}
|
71 |
if ($ChunkSize > 0) {
|
@@ -93,7 +96,7 @@ class getid3_vqf extends getid3_handler
|
|
93 |
$info['audio']['encoder_options'] = 'CBR' . ceil($info['audio']['bitrate']/1000);
|
94 |
|
95 |
if ($info['audio']['bitrate'] == 0) {
|
96 |
-
$
|
97 |
return false;
|
98 |
}
|
99 |
break;
|
@@ -112,7 +115,7 @@ class getid3_vqf extends getid3_handler
|
|
112 |
break;
|
113 |
|
114 |
default:
|
115 |
-
$
|
116 |
break;
|
117 |
}
|
118 |
}
|
@@ -123,12 +126,12 @@ class getid3_vqf extends getid3_handler
|
|
123 |
switch ($thisfile_vqf['DSIZ']) {
|
124 |
case 0:
|
125 |
case 1:
|
126 |
-
$
|
127 |
$info['audio']['encoder'] = 'Ahead Nero';
|
128 |
break;
|
129 |
|
130 |
default:
|
131 |
-
$
|
132 |
break;
|
133 |
}
|
134 |
}
|
@@ -136,6 +139,11 @@ class getid3_vqf extends getid3_handler
|
|
136 |
return true;
|
137 |
}
|
138 |
|
|
|
|
|
|
|
|
|
|
|
139 |
public function VQFchannelFrequencyLookup($frequencyid) {
|
140 |
static $VQFchannelFrequencyLookup = array(
|
141 |
11 => 11025,
|
@@ -145,6 +153,11 @@ class getid3_vqf extends getid3_handler
|
|
145 |
return (isset($VQFchannelFrequencyLookup[$frequencyid]) ? $VQFchannelFrequencyLookup[$frequencyid] : $frequencyid * 1000);
|
146 |
}
|
147 |
|
|
|
|
|
|
|
|
|
|
|
148 |
public function VQFcommentNiceNameLookup($shortname) {
|
149 |
static $VQFcommentNiceNameLookup = array(
|
150 |
'NAME' => 'title',
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.vqf.php //
|
17 |
|
18 |
class getid3_vqf extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @return bool
|
22 |
+
*/
|
23 |
public function Analyze() {
|
24 |
$info = &$this->getid3->info;
|
25 |
|
43 |
$thisfile_vqf_raw['header_tag'] = substr($VQFheaderData, $offset, 4);
|
44 |
$magic = 'TWIN';
|
45 |
if ($thisfile_vqf_raw['header_tag'] != $magic) {
|
46 |
+
$this->error('Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($thisfile_vqf_raw['header_tag']).'"');
|
47 |
unset($info['vqf']);
|
48 |
unset($info['fileformat']);
|
49 |
return false;
|
68 |
$ChunkSize = getid3_lib::BigEndian2Int(substr($ChunkData, $chunkoffset, 4));
|
69 |
$chunkoffset += 4;
|
70 |
if ($ChunkSize > ($info['avdataend'] - $this->ftell())) {
|
71 |
+
$this->error('Invalid chunk size ('.$ChunkSize.') for chunk "'.$ChunkName.'" at offset '.$ChunkBaseOffset);
|
72 |
break;
|
73 |
}
|
74 |
if ($ChunkSize > 0) {
|
96 |
$info['audio']['encoder_options'] = 'CBR' . ceil($info['audio']['bitrate']/1000);
|
97 |
|
98 |
if ($info['audio']['bitrate'] == 0) {
|
99 |
+
$this->error('Corrupt VQF file: bitrate_audio == zero');
|
100 |
return false;
|
101 |
}
|
102 |
break;
|
115 |
break;
|
116 |
|
117 |
default:
|
118 |
+
$this->warning('Unhandled chunk type "'.$ChunkName.'" at offset '.$ChunkBaseOffset);
|
119 |
break;
|
120 |
}
|
121 |
}
|
126 |
switch ($thisfile_vqf['DSIZ']) {
|
127 |
case 0:
|
128 |
case 1:
|
129 |
+
$this->warning('Invalid DSIZ value "'.$thisfile_vqf['DSIZ'].'". This is known to happen with VQF files encoded by Ahead Nero, and seems to be its way of saying this is TwinVQF v'.($thisfile_vqf['DSIZ'] + 1).'.0');
|
130 |
$info['audio']['encoder'] = 'Ahead Nero';
|
131 |
break;
|
132 |
|
133 |
default:
|
134 |
+
$this->warning('Probable corrupted file - should be '.$thisfile_vqf['DSIZ'].' bytes, actually '.($info['avdataend'] - $info['avdataoffset'] - strlen('DATA')));
|
135 |
break;
|
136 |
}
|
137 |
}
|
139 |
return true;
|
140 |
}
|
141 |
|
142 |
+
/**
|
143 |
+
* @param int $frequencyid
|
144 |
+
*
|
145 |
+
* @return int
|
146 |
+
*/
|
147 |
public function VQFchannelFrequencyLookup($frequencyid) {
|
148 |
static $VQFchannelFrequencyLookup = array(
|
149 |
11 => 11025,
|
153 |
return (isset($VQFchannelFrequencyLookup[$frequencyid]) ? $VQFchannelFrequencyLookup[$frequencyid] : $frequencyid * 1000);
|
154 |
}
|
155 |
|
156 |
+
/**
|
157 |
+
* @param string $shortname
|
158 |
+
*
|
159 |
+
* @return string
|
160 |
+
*/
|
161 |
public function VQFcommentNiceNameLookup($shortname) {
|
162 |
static $VQFcommentNiceNameLookup = array(
|
163 |
'NAME' => 'title',
|
lib/getid3/module.audio.wavpack.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
|
|
2 |
/////////////////////////////////////////////////////////////////
|
3 |
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
-
// available at
|
5 |
-
// or
|
6 |
-
//
|
7 |
-
|
8 |
-
// See readme.txt for more details //
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.wavpack.php //
|
@@ -17,7 +17,9 @@
|
|
17 |
|
18 |
class getid3_wavpack extends getid3_handler
|
19 |
{
|
20 |
-
|
|
|
|
|
21 |
public function Analyze() {
|
22 |
$info = &$this->getid3->info;
|
23 |
|
@@ -47,7 +49,7 @@ class getid3_wavpack extends getid3_handler
|
|
47 |
|
48 |
$magic = 'wvpk';
|
49 |
if ($blockheader_magic != $magic) {
|
50 |
-
$
|
51 |
switch (isset($info['audio']['dataformat']) ? $info['audio']['dataformat'] : '') {
|
52 |
case 'wavpack':
|
53 |
case 'wvc':
|
@@ -86,7 +88,7 @@ class getid3_wavpack extends getid3_handler
|
|
86 |
$info['wavpack']['blockheader']['size'] = $blockheader_size;
|
87 |
|
88 |
if ($info['wavpack']['blockheader']['size'] >= 0x100000) {
|
89 |
-
$
|
1 |
<?php
|
2 |
+
|
3 |
/////////////////////////////////////////////////////////////////
|
4 |
/// getID3() by James Heinrich <info@getid3.org> //
|
5 |
+
// available at https://github.com/JamesHeinrich/getID3 //
|
6 |
+
// or https://www.getid3.org //
|
7 |
+
// or http://getid3.sourceforge.net //
|
8 |
+
// see readme.txt for more details //
|
|
|
9 |
/////////////////////////////////////////////////////////////////
|
10 |
// //
|
11 |
// module.audio.wavpack.php //
|
17 |
|
18 |
class getid3_wavpack extends getid3_handler
|
19 |
{
|
20 |
+
/**
|
21 |
+
* @return bool
|
22 |
+
*/
|
23 |
public function Analyze() {
|
24 |
$info = &$this->getid3->info;
|
25 |
|
49 |
|
50 |
$magic = 'wvpk';
|
51 |
if ($blockheader_magic != $magic) {
|
52 |
+
$this->error('Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$blockheader_offset.', found "'.getid3_lib::PrintHexBytes($blockheader_magic).'"');
|
53 |
switch (isset($info['audio']['dataformat']) ? $info['audio']['dataformat'] : '') {
|
54 |
case 'wavpack':
|
55 |
case 'wvc':
|
88 |
$info['wavpack']['blockheader']['size'] = $blockheader_size;
|
89 |
|
90 |
if ($info['wavpack']['blockheader']['size'] >= 0x100000) {
|
91 |
+
$this->error('Expecting WavPack block size less than "0x100000", found "'.$info['wavpack']['blockheader']['size'].'" at offset '.$info['
|