Version Description
Download this release
Release Info
Developer | amandato |
Plugin | PowerPress Podcasting plugin by Blubrry |
Version | 0.2.0 |
Comparing to | |
See all releases |
Version 0.2.0
- FlowPlayerClassic.swf +0 -0
- getid3/getid3.lib.php +1306 -0
- getid3/getid3.php +1345 -0
- getid3/module.audio.mp3.php +1932 -0
- itunes_default.jpg +0 -0
- mp3info.class.php +259 -0
- player.js +373 -0
- powerpress.php +655 -0
- powerpressadmin.php +970 -0
- readme.txt +54 -0
- rss_default.jpg +0 -0
- screenshot-1.jpg +0 -0
- screenshot-2.jpg +0 -0
FlowPlayerClassic.swf
ADDED
Binary file
|
getid3/getid3.lib.php
ADDED
@@ -0,0 +1,1306 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/////////////////////////////////////////////////////////////////
|
3 |
+
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
+
// available at http://getid3.sourceforge.net //
|
5 |
+
// or http://www.getid3.org //
|
6 |
+
/////////////////////////////////////////////////////////////////
|
7 |
+
// //
|
8 |
+
// getid3.lib.php - part of getID3() //
|
9 |
+
// See readme.txt for more details //
|
10 |
+
// ///
|
11 |
+
/////////////////////////////////////////////////////////////////
|
12 |
+
|
13 |
+
|
14 |
+
class getid3_lib
|
15 |
+
{
|
16 |
+
|
17 |
+
function PrintHexBytes($string, $hex=true, $spaces=true, $htmlsafe=true) {
|
18 |
+
$returnstring = '';
|
19 |
+
for ($i = 0; $i < strlen($string); $i++) {
|
20 |
+
if ($hex) {
|
21 |
+
$returnstring .= str_pad(dechex(ord($string{$i})), 2, '0', STR_PAD_LEFT);
|
22 |
+
} else {
|
23 |
+
$returnstring .= ' '.(ereg("[\x20-\x7E]", $string{$i}) ? $string{$i} : '�');
|
24 |
+
}
|
25 |
+
if ($spaces) {
|
26 |
+
$returnstring .= ' ';
|
27 |
+
}
|
28 |
+
}
|
29 |
+
if ($htmlsafe) {
|
30 |
+
$returnstring = htmlentities($returnstring);
|
31 |
+
}
|
32 |
+
return $returnstring;
|
33 |
+
}
|
34 |
+
|
35 |
+
function SafeStripSlashes($text) {
|
36 |
+
if (get_magic_quotes_gpc()) {
|
37 |
+
return stripslashes($text);
|
38 |
+
}
|
39 |
+
return $text;
|
40 |
+
}
|
41 |
+
|
42 |
+
|
43 |
+
function trunc($floatnumber) {
|
44 |
+
// truncates a floating-point number at the decimal point
|
45 |
+
// returns int (if possible, otherwise float)
|
46 |
+
if ($floatnumber >= 1) {
|
47 |
+
$truncatednumber = floor($floatnumber);
|
48 |
+
} elseif ($floatnumber <= -1) {
|
49 |
+
$truncatednumber = ceil($floatnumber);
|
50 |
+
} else {
|
51 |
+
$truncatednumber = 0;
|
52 |
+
}
|
53 |
+
if ($truncatednumber <= 1073741824) { // 2^30
|
54 |
+
$truncatednumber = (int) $truncatednumber;
|
55 |
+
}
|
56 |
+
return $truncatednumber;
|
57 |
+
}
|
58 |
+
|
59 |
+
|
60 |
+
function CastAsInt($floatnum) {
|
61 |
+
// convert to float if not already
|
62 |
+
$floatnum = (float) $floatnum;
|
63 |
+
|
64 |
+
// convert a float to type int, only if possible
|
65 |
+
if (getid3_lib::trunc($floatnum) == $floatnum) {
|
66 |
+
// it's not floating point
|
67 |
+
if ($floatnum <= 1073741824) { // 2^30
|
68 |
+
// it's within int range
|
69 |
+
$floatnum = (int) $floatnum;
|
70 |
+
}
|
71 |
+
}
|
72 |
+
return $floatnum;
|
73 |
+
}
|
74 |
+
|
75 |
+
|
76 |
+
function DecimalBinary2Float($binarynumerator) {
|
77 |
+
$numerator = getid3_lib::Bin2Dec($binarynumerator);
|
78 |
+
$denominator = getid3_lib::Bin2Dec('1'.str_repeat('0', strlen($binarynumerator)));
|
79 |
+
return ($numerator / $denominator);
|
80 |
+
}
|
81 |
+
|
82 |
+
|
83 |
+
function NormalizeBinaryPoint($binarypointnumber, $maxbits=52) {
|
84 |
+
// http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
|
85 |
+
if (strpos($binarypointnumber, '.') === false) {
|
86 |
+
$binarypointnumber = '0.'.$binarypointnumber;
|
87 |
+
} elseif ($binarypointnumber{0} == '.') {
|
88 |
+
$binarypointnumber = '0'.$binarypointnumber;
|
89 |
+
}
|
90 |
+
$exponent = 0;
|
91 |
+
while (($binarypointnumber{0} != '1') || (substr($binarypointnumber, 1, 1) != '.')) {
|
92 |
+
if (substr($binarypointnumber, 1, 1) == '.') {
|
93 |
+
$exponent--;
|
94 |
+
$binarypointnumber = substr($binarypointnumber, 2, 1).'.'.substr($binarypointnumber, 3);
|
95 |
+
} else {
|
96 |
+
$pointpos = strpos($binarypointnumber, '.');
|
97 |
+
$exponent += ($pointpos - 1);
|
98 |
+
$binarypointnumber = str_replace('.', '', $binarypointnumber);
|
99 |
+
$binarypointnumber = $binarypointnumber{0}.'.'.substr($binarypointnumber, 1);
|
100 |
+
}
|
101 |
+
}
|
102 |
+
$binarypointnumber = str_pad(substr($binarypointnumber, 0, $maxbits + 2), $maxbits + 2, '0', STR_PAD_RIGHT);
|
103 |
+
return array('normalized'=>$binarypointnumber, 'exponent'=>(int) $exponent);
|
104 |
+
}
|
105 |
+
|
106 |
+
|
107 |
+
function Float2BinaryDecimal($floatvalue) {
|
108 |
+
// http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
|
109 |
+
$maxbits = 128; // to how many bits of precision should the calculations be taken?
|
110 |
+
$intpart = getid3_lib::trunc($floatvalue);
|
111 |
+
$floatpart = abs($floatvalue - $intpart);
|
112 |
+
$pointbitstring = '';
|
113 |
+
while (($floatpart != 0) && (strlen($pointbitstring) < $maxbits)) {
|
114 |
+
$floatpart *= 2;
|
115 |
+
$pointbitstring .= (string) getid3_lib::trunc($floatpart);
|
116 |
+
$floatpart -= getid3_lib::trunc($floatpart);
|
117 |
+
}
|
118 |
+
$binarypointnumber = decbin($intpart).'.'.$pointbitstring;
|
119 |
+
return $binarypointnumber;
|
120 |
+
}
|
121 |
+
|
122 |
+
|
123 |
+
function Float2String($floatvalue, $bits) {
|
124 |
+
// http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html
|
125 |
+
switch ($bits) {
|
126 |
+
case 32:
|
127 |
+
$exponentbits = 8;
|
128 |
+
$fractionbits = 23;
|
129 |
+
break;
|
130 |
+
|
131 |
+
case 64:
|
132 |
+
$exponentbits = 11;
|
133 |
+
$fractionbits = 52;
|
134 |
+
break;
|
135 |
+
|
136 |
+
default:
|
137 |
+
return false;
|
138 |
+
break;
|
139 |
+
}
|
140 |
+
if ($floatvalue >= 0) {
|
141 |
+
$signbit = '0';
|
142 |
+
} else {
|
143 |
+
$signbit = '1';
|
144 |
+
}
|
145 |
+
$normalizedbinary = getid3_lib::NormalizeBinaryPoint(getid3_lib::Float2BinaryDecimal($floatvalue), $fractionbits);
|
146 |
+
$biasedexponent = pow(2, $exponentbits - 1) - 1 + $normalizedbinary['exponent']; // (127 or 1023) +/- exponent
|
147 |
+
$exponentbitstring = str_pad(decbin($biasedexponent), $exponentbits, '0', STR_PAD_LEFT);
|
148 |
+
$fractionbitstring = str_pad(substr($normalizedbinary['normalized'], 2), $fractionbits, '0', STR_PAD_RIGHT);
|
149 |
+
|
150 |
+
return getid3_lib::BigEndian2String(getid3_lib::Bin2Dec($signbit.$exponentbitstring.$fractionbitstring), $bits % 8, false);
|
151 |
+
}
|
152 |
+
|
153 |
+
|
154 |
+
function LittleEndian2Float($byteword) {
|
155 |
+
return getid3_lib::BigEndian2Float(strrev($byteword));
|
156 |
+
}
|
157 |
+
|
158 |
+
|
159 |
+
function BigEndian2Float($byteword) {
|
160 |
+
// ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic
|
161 |
+
// http://www.psc.edu/general/software/packages/ieee/ieee.html
|
162 |
+
// http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html
|
163 |
+
|
164 |
+
$bitword = getid3_lib::BigEndian2Bin($byteword);
|
165 |
+
if (!$bitword) {
|
166 |
+
return 0;
|
167 |
+
}
|
168 |
+
$signbit = $bitword{0};
|
169 |
+
|
170 |
+
switch (strlen($byteword) * 8) {
|
171 |
+
case 32:
|
172 |
+
$exponentbits = 8;
|
173 |
+
$fractionbits = 23;
|
174 |
+
break;
|
175 |
+
|
176 |
+
case 64:
|
177 |
+
$exponentbits = 11;
|
178 |
+
$fractionbits = 52;
|
179 |
+
break;
|
180 |
+
|
181 |
+
case 80:
|
182 |
+
// 80-bit Apple SANE format
|
183 |
+
// http://www.mactech.com/articles/mactech/Vol.06/06.01/SANENormalized/
|
184 |
+
$exponentstring = substr($bitword, 1, 15);
|
185 |
+
$isnormalized = intval($bitword{16});
|
186 |
+
$fractionstring = substr($bitword, 17, 63);
|
187 |
+
$exponent = pow(2, getid3_lib::Bin2Dec($exponentstring) - 16383);
|
188 |
+
$fraction = $isnormalized + getid3_lib::DecimalBinary2Float($fractionstring);
|
189 |
+
$floatvalue = $exponent * $fraction;
|
190 |
+
if ($signbit == '1') {
|
191 |
+
$floatvalue *= -1;
|
192 |
+
}
|
193 |
+
return $floatvalue;
|
194 |
+
break;
|
195 |
+
|
196 |
+
default:
|
197 |
+
return false;
|
198 |
+
break;
|
199 |
+
}
|
200 |
+
$exponentstring = substr($bitword, 1, $exponentbits);
|
201 |
+
$fractionstring = substr($bitword, $exponentbits + 1, $fractionbits);
|
202 |
+
$exponent = getid3_lib::Bin2Dec($exponentstring);
|
203 |
+
$fraction = getid3_lib::Bin2Dec($fractionstring);
|
204 |
+
|
205 |
+
if (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction != 0)) {
|
206 |
+
// Not a Number
|
207 |
+
$floatvalue = false;
|
208 |
+
} elseif (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction == 0)) {
|
209 |
+
if ($signbit == '1') {
|
210 |
+
$floatvalue = '-infinity';
|
211 |
+
} else {
|
212 |
+
$floatvalue = '+infinity';
|
213 |
+
}
|
214 |
+
} elseif (($exponent == 0) && ($fraction == 0)) {
|
215 |
+
if ($signbit == '1') {
|
216 |
+
$floatvalue = -0;
|
217 |
+
} else {
|
218 |
+
$floatvalue = 0;
|
219 |
+
}
|
220 |
+
$floatvalue = ($signbit ? 0 : -0);
|
221 |
+
} elseif (($exponent == 0) && ($fraction != 0)) {
|
222 |
+
// These are 'unnormalized' values
|
223 |
+
$floatvalue = pow(2, (-1 * (pow(2, $exponentbits - 1) - 2))) * getid3_lib::DecimalBinary2Float($fractionstring);
|
224 |
+
if ($signbit == '1') {
|
225 |
+
$floatvalue *= -1;
|
226 |
+
}
|
227 |
+
} elseif ($exponent != 0) {
|
228 |
+
$floatvalue = pow(2, ($exponent - (pow(2, $exponentbits - 1) - 1))) * (1 + getid3_lib::DecimalBinary2Float($fractionstring));
|
229 |
+
if ($signbit == '1') {
|
230 |
+
$floatvalue *= -1;
|
231 |
+
}
|
232 |
+
}
|
233 |
+
return (float) $floatvalue;
|
234 |
+
}
|
235 |
+
|
236 |
+
|
237 |
+
function BigEndian2Int($byteword, $synchsafe=false, $signed=false) {
|
238 |
+
$intvalue = 0;
|
239 |
+
$bytewordlen = strlen($byteword);
|
240 |
+
for ($i = 0; $i < $bytewordlen; $i++) {
|
241 |
+
if ($synchsafe) { // disregard MSB, effectively 7-bit bytes
|
242 |
+
$intvalue = $intvalue | (ord($byteword{$i}) & 0x7F) << (($bytewordlen - 1 - $i) * 7);
|
243 |
+
} else {
|
244 |
+
$intvalue += ord($byteword{$i}) * pow(256, ($bytewordlen - 1 - $i));
|
245 |
+
}
|
246 |
+
}
|
247 |
+
if ($signed && !$synchsafe) {
|
248 |
+
// synchsafe ints are not allowed to be signed
|
249 |
+
switch ($bytewordlen) {
|
250 |
+
case 1:
|
251 |
+
case 2:
|
252 |
+
case 3:
|
253 |
+
case 4:
|
254 |
+
$signmaskbit = 0x80 << (8 * ($bytewordlen - 1));
|
255 |
+
if ($intvalue & $signmaskbit) {
|
256 |
+
$intvalue = 0 - ($intvalue & ($signmaskbit - 1));
|
257 |
+
}
|
258 |
+
break;
|
259 |
+
|
260 |
+
default:
|
261 |
+
die('ERROR: Cannot have signed integers larger than 32-bits in getid3_lib::BigEndian2Int()');
|
262 |
+
break;
|
263 |
+
}
|
264 |
+
}
|
265 |
+
return getid3_lib::CastAsInt($intvalue);
|
266 |
+
}
|
267 |
+
|
268 |
+
|
269 |
+
function LittleEndian2Int($byteword, $signed=false) {
|
270 |
+
return getid3_lib::BigEndian2Int(strrev($byteword), false, $signed);
|
271 |
+
}
|
272 |
+
|
273 |
+
|
274 |
+
function BigEndian2Bin($byteword) {
|
275 |
+
$binvalue = '';
|
276 |
+
$bytewordlen = strlen($byteword);
|
277 |
+
for ($i = 0; $i < $bytewordlen; $i++) {
|
278 |
+
$binvalue .= str_pad(decbin(ord($byteword{$i})), 8, '0', STR_PAD_LEFT);
|
279 |
+
}
|
280 |
+
return $binvalue;
|
281 |
+
}
|
282 |
+
|
283 |
+
|
284 |
+
function BigEndian2String($number, $minbytes=1, $synchsafe=false, $signed=false) {
|
285 |
+
if ($number < 0) {
|
286 |
+
return false;
|
287 |
+
}
|
288 |
+
$maskbyte = (($synchsafe || $signed) ? 0x7F : 0xFF);
|
289 |
+
$intstring = '';
|
290 |
+
if ($signed) {
|
291 |
+
if ($minbytes > 4) {
|
292 |
+
die('ERROR: Cannot have signed integers larger than 32-bits in getid3_lib::BigEndian2String()');
|
293 |
+
}
|
294 |
+
$number = $number & (0x80 << (8 * ($minbytes - 1)));
|
295 |
+
}
|
296 |
+
while ($number != 0) {
|
297 |
+
$quotient = ($number / ($maskbyte + 1));
|
298 |
+
$intstring = chr(ceil(($quotient - floor($quotient)) * $maskbyte)).$intstring;
|
299 |
+
$number = floor($quotient);
|
300 |
+
}
|
301 |
+
return str_pad($intstring, $minbytes, "\x00", STR_PAD_LEFT);
|
302 |
+
}
|
303 |
+
|
304 |
+
|
305 |
+
function Dec2Bin($number) {
|
306 |
+
while ($number >= 256) {
|
307 |
+
$bytes[] = (($number / 256) - (floor($number / 256))) * 256;
|
308 |
+
$number = floor($number / 256);
|
309 |
+
}
|
310 |
+
$bytes[] = $number;
|
311 |
+
$binstring = '';
|
312 |
+
for ($i = 0; $i < count($bytes); $i++) {
|
313 |
+
$binstring = (($i == count($bytes) - 1) ? decbin($bytes[$i]) : str_pad(decbin($bytes[$i]), 8, '0', STR_PAD_LEFT)).$binstring;
|
314 |
+
}
|
315 |
+
return $binstring;
|
316 |
+
}
|
317 |
+
|
318 |
+
|
319 |
+
function Bin2Dec($binstring, $signed=false) {
|
320 |
+
$signmult = 1;
|
321 |
+
if ($signed) {
|
322 |
+
if ($binstring{0} == '1') {
|
323 |
+
$signmult = -1;
|
324 |
+
}
|
325 |
+
$binstring = substr($binstring, 1);
|
326 |
+
}
|
327 |
+
$decvalue = 0;
|
328 |
+
for ($i = 0; $i < strlen($binstring); $i++) {
|
329 |
+
$decvalue += ((int) substr($binstring, strlen($binstring) - $i - 1, 1)) * pow(2, $i);
|
330 |
+
}
|
331 |
+
return getid3_lib::CastAsInt($decvalue * $signmult);
|
332 |
+
}
|
333 |
+
|
334 |
+
|
335 |
+
function Bin2String($binstring) {
|
336 |
+
// return 'hi' for input of '0110100001101001'
|
337 |
+
$string = '';
|
338 |
+
$binstringreversed = strrev($binstring);
|
339 |
+
for ($i = 0; $i < strlen($binstringreversed); $i += 8) {
|
340 |
+
$string = chr(getid3_lib::Bin2Dec(strrev(substr($binstringreversed, $i, 8)))).$string;
|
341 |
+
}
|
342 |
+
return $string;
|
343 |
+
}
|
344 |
+
|
345 |
+
|
346 |
+
function LittleEndian2String($number, $minbytes=1, $synchsafe=false) {
|
347 |
+
$intstring = '';
|
348 |
+
while ($number > 0) {
|
349 |
+
if ($synchsafe) {
|
350 |
+
$intstring = $intstring.chr($number & 127);
|
351 |
+
$number >>= 7;
|
352 |
+
} else {
|
353 |
+
$intstring = $intstring.chr($number & 255);
|
354 |
+
$number >>= 8;
|
355 |
+
}
|
356 |
+
}
|
357 |
+
return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT);
|
358 |
+
}
|
359 |
+
|
360 |
+
|
361 |
+
function array_merge_clobber($array1, $array2) {
|
362 |
+
// written by kc�hireability*com
|
363 |
+
// taken from http://www.php.net/manual/en/function.array-merge-recursive.php
|
364 |
+
if (!is_array($array1) || !is_array($array2)) {
|
365 |
+
return false;
|
366 |
+
}
|
367 |
+
$newarray = $array1;
|
368 |
+
foreach ($array2 as $key => $val) {
|
369 |
+
if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) {
|
370 |
+
$newarray[$key] = getid3_lib::array_merge_clobber($newarray[$key], $val);
|
371 |
+
} else {
|
372 |
+
$newarray[$key] = $val;
|
373 |
+
}
|
374 |
+
}
|
375 |
+
return $newarray;
|
376 |
+
}
|
377 |
+
|
378 |
+
|
379 |
+
function array_merge_noclobber($array1, $array2) {
|
380 |
+
if (!is_array($array1) || !is_array($array2)) {
|
381 |
+
return false;
|
382 |
+
}
|
383 |
+
$newarray = $array1;
|
384 |
+
foreach ($array2 as $key => $val) {
|
385 |
+
if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) {
|
386 |
+
$newarray[$key] = getid3_lib::array_merge_noclobber($newarray[$key], $val);
|
387 |
+
} elseif (!isset($newarray[$key])) {
|
388 |
+
$newarray[$key] = $val;
|
389 |
+
}
|
390 |
+
}
|
391 |
+
return $newarray;
|
392 |
+
}
|
393 |
+
|
394 |
+
|
395 |
+
function fileextension($filename, $numextensions=1) {
|
396 |
+
if (strstr($filename, '.')) {
|
397 |
+
$reversedfilename = strrev($filename);
|
398 |
+
$offset = 0;
|
399 |
+
for ($i = 0; $i < $numextensions; $i++) {
|
400 |
+
$offset = strpos($reversedfilename, '.', $offset + 1);
|
401 |
+
if ($offset === false) {
|
402 |
+
return '';
|
403 |
+
}
|
404 |
+
}
|
405 |
+
return strrev(substr($reversedfilename, 0, $offset));
|
406 |
+
}
|
407 |
+
return '';
|
408 |
+
}
|
409 |
+
|
410 |
+
|
411 |
+
function PlaytimeString($playtimeseconds) {
|
412 |
+
$sign = (($playtimeseconds < 0) ? '-' : '');
|
413 |
+
$playtimeseconds = abs($playtimeseconds);
|
414 |
+
$contentseconds = round((($playtimeseconds / 60) - floor($playtimeseconds / 60)) * 60);
|
415 |
+
$contentminutes = floor($playtimeseconds / 60);
|
416 |
+
if ($contentseconds >= 60) {
|
417 |
+
$contentseconds -= 60;
|
418 |
+
$contentminutes++;
|
419 |
+
}
|
420 |
+
return $sign.intval($contentminutes).':'.str_pad($contentseconds, 2, 0, STR_PAD_LEFT);
|
421 |
+
}
|
422 |
+
|
423 |
+
|
424 |
+
function image_type_to_mime_type($imagetypeid) {
|
425 |
+
// only available in PHP v4.3.0+
|
426 |
+
static $image_type_to_mime_type = array();
|
427 |
+
if (empty($image_type_to_mime_type)) {
|
428 |
+
$image_type_to_mime_type[1] = 'image/gif'; // GIF
|
429 |
+
$image_type_to_mime_type[2] = 'image/jpeg'; // JPEG
|
430 |
+
$image_type_to_mime_type[3] = 'image/png'; // PNG
|
431 |
+
$image_type_to_mime_type[4] = 'application/x-shockwave-flash'; // Flash
|
432 |
+
$image_type_to_mime_type[5] = 'image/psd'; // PSD
|
433 |
+
$image_type_to_mime_type[6] = 'image/bmp'; // BMP
|
434 |
+
$image_type_to_mime_type[7] = 'image/tiff'; // TIFF: little-endian (Intel)
|
435 |
+
$image_type_to_mime_type[8] = 'image/tiff'; // TIFF: big-endian (Motorola)
|
436 |
+
//$image_type_to_mime_type[9] = 'image/jpc'; // JPC
|
437 |
+
//$image_type_to_mime_type[10] = 'image/jp2'; // JPC
|
438 |
+
//$image_type_to_mime_type[11] = 'image/jpx'; // JPC
|
439 |
+
//$image_type_to_mime_type[12] = 'image/jb2'; // JPC
|
440 |
+
$image_type_to_mime_type[13] = 'application/x-shockwave-flash'; // Shockwave
|
441 |
+
$image_type_to_mime_type[14] = 'image/iff'; // IFF
|
442 |
+
}
|
443 |
+
return (isset($image_type_to_mime_type[$imagetypeid]) ? $image_type_to_mime_type[$imagetypeid] : 'application/octet-stream');
|
444 |
+
}
|
445 |
+
|
446 |
+
|
447 |
+
function DateMac2Unix($macdate) {
|
448 |
+
// Macintosh timestamp: seconds since 00:00h January 1, 1904
|
449 |
+
// UNIX timestamp: seconds since 00:00h January 1, 1970
|
450 |
+
return getid3_lib::CastAsInt($macdate - 2082844800);
|
451 |
+
}
|
452 |
+
|
453 |
+
|
454 |
+
function FixedPoint8_8($rawdata) {
|
455 |
+
return getid3_lib::BigEndian2Int(substr($rawdata, 0, 1)) + (float) (getid3_lib::BigEndian2Int(substr($rawdata, 1, 1)) / pow(2, 8));
|
456 |
+
}
|
457 |
+
|
458 |
+
|
459 |
+
function FixedPoint16_16($rawdata) {
|
460 |
+
return getid3_lib::BigEndian2Int(substr($rawdata, 0, 2)) + (float) (getid3_lib::BigEndian2Int(substr($rawdata, 2, 2)) / pow(2, 16));
|
461 |
+
}
|
462 |
+
|
463 |
+
|
464 |
+
function FixedPoint2_30($rawdata) {
|
465 |
+
$binarystring = getid3_lib::BigEndian2Bin($rawdata);
|
466 |
+
return getid3_lib::Bin2Dec(substr($binarystring, 0, 2)) + (float) (getid3_lib::Bin2Dec(substr($binarystring, 2, 30)) / 1073741824);
|
467 |
+
}
|
468 |
+
|
469 |
+
|
470 |
+
function CreateDeepArray($ArrayPath, $Separator, $Value) {
|
471 |
+
// assigns $Value to a nested array path:
|
472 |
+
// $foo = getid3_lib::CreateDeepArray('/path/to/my', '/', 'file.txt')
|
473 |
+
// is the same as:
|
474 |
+
// $foo = array('path'=>array('to'=>'array('my'=>array('file.txt'))));
|
475 |
+
// or
|
476 |
+
// $foo['path']['to']['my'] = 'file.txt';
|
477 |
+
while ($ArrayPath && ($ArrayPath{0} == $Separator)) {
|
478 |
+
$ArrayPath = substr($ArrayPath, 1);
|
479 |
+
}
|
480 |
+
if (($pos = strpos($ArrayPath, $Separator)) !== false) {
|
481 |
+
$ReturnedArray[substr($ArrayPath, 0, $pos)] = getid3_lib::CreateDeepArray(substr($ArrayPath, $pos + 1), $Separator, $Value);
|
482 |
+
} else {
|
483 |
+
$ReturnedArray[$ArrayPath] = $Value;
|
484 |
+
}
|
485 |
+
return $ReturnedArray;
|
486 |
+
}
|
487 |
+
|
488 |
+
function array_max($arraydata, $returnkey=false) {
|
489 |
+
$maxvalue = false;
|
490 |
+
$maxkey = false;
|
491 |
+
foreach ($arraydata as $key => $value) {
|
492 |
+
if (!is_array($value)) {
|
493 |
+
if ($value > $maxvalue) {
|
494 |
+
$maxvalue = $value;
|
495 |
+
$maxkey = $key;
|
496 |
+
}
|
497 |
+
}
|
498 |
+
}
|
499 |
+
return ($returnkey ? $maxkey : $maxvalue);
|
500 |
+
}
|
501 |
+
|
502 |
+
function array_min($arraydata, $returnkey=false) {
|
503 |
+
$minvalue = false;
|
504 |
+
$minkey = false;
|
505 |
+
foreach ($arraydata as $key => $value) {
|
506 |
+
if (!is_array($value)) {
|
507 |
+
if ($value > $minvalue) {
|
508 |
+
$minvalue = $value;
|
509 |
+
$minkey = $key;
|
510 |
+
}
|
511 |
+
}
|
512 |
+
}
|
513 |
+
return ($returnkey ? $minkey : $minvalue);
|
514 |
+
}
|
515 |
+
|
516 |
+
|
517 |
+
function md5_file($file) {
|
518 |
+
|
519 |
+
// md5_file() exists in PHP 4.2.0+.
|
520 |
+
if (function_exists('md5_file')) {
|
521 |
+
return md5_file($file);
|
522 |
+
}
|
523 |
+
|
524 |
+
if (GETID3_OS_ISWINDOWS) {
|
525 |
+
|
526 |
+
$RequiredFiles = array('cygwin1.dll', 'md5sum.exe');
|
527 |
+
foreach ($RequiredFiles as $required_file) {
|
528 |
+
if (!is_readable(GETID3_HELPERAPPSDIR.$required_file)) {
|
529 |
+
die(implode(' and ', $RequiredFiles).' are required in '.GETID3_HELPERAPPSDIR.' for getid3_lib::md5_file() to function under Windows in PHP < v4.2.0');
|
530 |
+
}
|
531 |
+
}
|
532 |
+
$commandline = GETID3_HELPERAPPSDIR.'md5sum.exe "'.str_replace('/', DIRECTORY_SEPARATOR, $file).'"';
|
533 |
+
if (ereg("^[\\]?([0-9a-f]{32})", strtolower(`$commandline`), $r)) {
|
534 |
+
return $r[1];
|
535 |
+
}
|
536 |
+
|
537 |
+
} else {
|
538 |
+
|
539 |
+
// The following works under UNIX only
|
540 |
+
$file = str_replace('`', '\\`', $file);
|
541 |
+
if (ereg("^([0-9a-f]{32})[ \t\n\r]", `md5sum "$file"`, $r)) {
|
542 |
+
return $r[1];
|
543 |
+
}
|
544 |
+
|
545 |
+
}
|
546 |
+
return false;
|
547 |
+
}
|
548 |
+
|
549 |
+
|
550 |
+
function sha1_file($file) {
|
551 |
+
|
552 |
+
// sha1_file() exists in PHP 4.3.0+.
|
553 |
+
if (function_exists('sha1_file')) {
|
554 |
+
return sha1_file($file);
|
555 |
+
}
|
556 |
+
|
557 |
+
$file = str_replace('`', '\\`', $file);
|
558 |
+
|
559 |
+
if (GETID3_OS_ISWINDOWS) {
|
560 |
+
|
561 |
+
$RequiredFiles = array('cygwin1.dll', 'sha1sum.exe');
|
562 |
+
foreach ($RequiredFiles as $required_file) {
|
563 |
+
if (!is_readable(GETID3_HELPERAPPSDIR.$required_file)) {
|
564 |
+
die(implode(' and ', $RequiredFiles).' are required in '.GETID3_HELPERAPPSDIR.' for getid3_lib::sha1_file() to function under Windows in PHP < v4.3.0');
|
565 |
+
}
|
566 |
+
}
|
567 |
+
$commandline = GETID3_HELPERAPPSDIR.'sha1sum.exe "'.str_replace('/', DIRECTORY_SEPARATOR, $file).'"';
|
568 |
+
if (ereg("^sha1=([0-9a-f]{40})", strtolower(`$commandline`), $r)) {
|
569 |
+
return $r[1];
|
570 |
+
}
|
571 |
+
|
572 |
+
} else {
|
573 |
+
|
574 |
+
$commandline = 'sha1sum '.escapeshellarg($file).'';
|
575 |
+
if (ereg("^([0-9a-f]{40})[ \t\n\r]", strtolower(`$commandline`), $r)) {
|
576 |
+
return $r[1];
|
577 |
+
}
|
578 |
+
|
579 |
+
}
|
580 |
+
|
581 |
+
return false;
|
582 |
+
}
|
583 |
+
|
584 |
+
|
585 |
+
// Allan Hansen <ah�artemis*dk>
|
586 |
+
// getid3_lib::md5_data() - returns md5sum for a file from startuing position to absolute end position
|
587 |
+
function hash_data($file, $offset, $end, $algorithm) {
|
588 |
+
|
589 |
+
switch ($algorithm) {
|
590 |
+
case 'md5':
|
591 |
+
$hash_function = 'md5_file';
|
592 |
+
$unix_call = 'md5sum';
|
593 |
+
$windows_call = 'md5sum.exe';
|
594 |
+
$hash_length = 32;
|
595 |
+
break;
|
596 |
+
|
597 |
+
case 'sha1':
|
598 |
+
$hash_function = 'sha1_file';
|
599 |
+
$unix_call = 'sha1sum';
|
600 |
+
$windows_call = 'sha1sum.exe';
|
601 |
+
$hash_length = 40;
|
602 |
+
break;
|
603 |
+
|
604 |
+
default:
|
605 |
+
die('Invalid algorithm ('.$algorithm.') in getid3_lib::hash_data()');
|
606 |
+
break;
|
607 |
+
}
|
608 |
+
$size = $end - $offset;
|
609 |
+
while (true) {
|
610 |
+
if (GETID3_OS_ISWINDOWS) {
|
611 |
+
|
612 |
+
// It seems that sha1sum.exe for Windows only works on physical files, does not accept piped data
|
613 |
+
// Fall back to create-temp-file method:
|
614 |
+
if ($algorithm == 'sha1') {
|
615 |
+
break;
|
616 |
+
}
|
617 |
+
|
618 |
+
$RequiredFiles = array('cygwin1.dll', 'head.exe', 'tail.exe', $windows_call);
|
619 |
+
foreach ($RequiredFiles as $required_file) {
|
620 |
+
if (!is_readable(GETID3_HELPERAPPSDIR.$required_file)) {
|
621 |
+
// helper apps not available - fall back to old method
|
622 |
+
break;
|
623 |
+
}
|
624 |
+
}
|
625 |
+
$commandline = GETID3_HELPERAPPSDIR.'head.exe -c '.$end.' "'.escapeshellarg(str_replace('/', DIRECTORY_SEPARATOR, $file)).'" | ';
|
626 |
+
$commandline .= GETID3_HELPERAPPSDIR.'tail.exe -c '.$size.' | ';
|
627 |
+
$commandline .= GETID3_HELPERAPPSDIR.$windows_call;
|
628 |
+
|
629 |
+
} else {
|
630 |
+
|
631 |
+
$commandline = 'head -c'.$end.' '.escapeshellarg($file).' | ';
|
632 |
+
$commandline .= 'tail -c'.$size.' | ';
|
633 |
+
$commandline .= $unix_call;
|
634 |
+
|
635 |
+
}
|
636 |
+
if ((bool) ini_get('safe_mode')) {
|
637 |
+
$ThisFileInfo['warning'][] = 'PHP running in Safe Mode - backtick operator not available, using slower non-system-call '.$algorithm.' algorithm';
|
638 |
+
break;
|
639 |
+
}
|
640 |
+
return substr(`$commandline`, 0, $hash_length);
|
641 |
+
}
|
642 |
+
|
643 |
+
// try to create a temporary file in the system temp directory - invalid dirname should force to system temp dir
|
644 |
+
if (($data_filename = tempnam('*', 'getID3')) === false) {
|
645 |
+
// can't find anywhere to create a temp file, just die
|
646 |
+
return false;
|
647 |
+
}
|
648 |
+
|
649 |
+
// Init
|
650 |
+
$result = false;
|
651 |
+
|
652 |
+
// copy parts of file
|
653 |
+
if ($fp = @fopen($file, 'rb')) {
|
654 |
+
|
655 |
+
if ($fp_data = @fopen($data_filename, 'wb')) {
|
656 |
+
|
657 |
+
fseek($fp, $offset, SEEK_SET);
|
658 |
+
$byteslefttowrite = $end - $offset;
|
659 |
+
while (($byteslefttowrite > 0) && ($buffer = fread($fp, GETID3_FREAD_BUFFER_SIZE))) {
|
660 |
+
$byteswritten = fwrite($fp_data, $buffer, $byteslefttowrite);
|
661 |
+
$byteslefttowrite -= $byteswritten;
|
662 |
+
}
|
663 |
+
fclose($fp_data);
|
664 |
+
$result = getid3_lib::$hash_function($data_filename);
|
665 |
+
|
666 |
+
}
|
667 |
+
fclose($fp);
|
668 |
+
}
|
669 |
+
unlink($data_filename);
|
670 |
+
return $result;
|
671 |
+
}
|
672 |
+
|
673 |
+
|
674 |
+
function iconv_fallback_int_utf8($charval) {
|
675 |
+
if ($charval < 128) {
|
676 |
+
// 0bbbbbbb
|
677 |
+
$newcharstring = chr($charval);
|
678 |
+
} elseif ($charval < 2048) {
|
679 |
+
// 110bbbbb 10bbbbbb
|
680 |
+
$newcharstring = chr(($charval >> 6) | 0xC0);
|
681 |
+
$newcharstring .= chr(($charval & 0x3F) | 0x80);
|
682 |
+
} elseif ($charval < 65536) {
|
683 |
+
// 1110bbbb 10bbbbbb 10bbbbbb
|
684 |
+
$newcharstring = chr(($charval >> 12) | 0xE0);
|
685 |
+
$newcharstring .= chr(($charval >> 6) | 0xC0);
|
686 |
+
$newcharstring .= chr(($charval & 0x3F) | 0x80);
|
687 |
+
} else {
|
688 |
+
// 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
|
689 |
+
$newcharstring = chr(($charval >> 18) | 0xF0);
|
690 |
+
$newcharstring .= chr(($charval >> 12) | 0xC0);
|
691 |
+
$newcharstring .= chr(($charval >> 6) | 0xC0);
|
692 |
+
$newcharstring .= chr(($charval & 0x3F) | 0x80);
|
693 |
+
}
|
694 |
+
return $newcharstring;
|
695 |
+
}
|
696 |
+
|
697 |
+
// ISO-8859-1 => UTF-8
|
698 |
+
function iconv_fallback_iso88591_utf8($string, $bom=false) {
|
699 |
+
if (function_exists('utf8_encode')) {
|
700 |
+
return utf8_encode($string);
|
701 |
+
}
|
702 |
+
// utf8_encode() unavailable, use getID3()'s iconv_fallback() conversions (possibly PHP is compiled without XML support)
|
703 |
+
$newcharstring = '';
|
704 |
+
if ($bom) {
|
705 |
+
$newcharstring .= "\xEF\xBB\xBF";
|
706 |
+
}
|
707 |
+
for ($i = 0; $i < strlen($string); $i++) {
|
708 |
+
$charval = ord($string{$i});
|
709 |
+
$newcharstring .= getid3_lib::iconv_fallback_int_utf8($charval);
|
710 |
+
}
|
711 |
+
return $newcharstring;
|
712 |
+
}
|
713 |
+
|
714 |
+
// ISO-8859-1 => UTF-16BE
|
715 |
+
function iconv_fallback_iso88591_utf16be($string, $bom=false) {
|
716 |
+
$newcharstring = '';
|
717 |
+
if ($bom) {
|
718 |
+
$newcharstring .= "\xFE\xFF";
|
719 |
+
}
|
720 |
+
for ($i = 0; $i < strlen($string); $i++) {
|
721 |
+
$newcharstring .= "\x00".$string{$i};
|
722 |
+
}
|
723 |
+
return $newcharstring;
|
724 |
+
}
|
725 |
+
|
726 |
+
// ISO-8859-1 => UTF-16LE
|
727 |
+
function iconv_fallback_iso88591_utf16le($string, $bom=false) {
|
728 |
+
$newcharstring = '';
|
729 |
+
if ($bom) {
|
730 |
+
$newcharstring .= "\xFF\xFE";
|
731 |
+
}
|
732 |
+
for ($i = 0; $i < strlen($string); $i++) {
|
733 |
+
$newcharstring .= $string{$i}."\x00";
|
734 |
+
}
|
735 |
+
return $newcharstring;
|
736 |
+
}
|
737 |
+
|
738 |
+
// ISO-8859-1 => UTF-16LE (BOM)
|
739 |
+
function iconv_fallback_iso88591_utf16($string) {
|
740 |
+
return getid3_lib::iconv_fallback_iso88591_utf16le($string, true);
|
741 |
+
}
|
742 |
+
|
743 |
+
// UTF-8 => ISO-8859-1
|
744 |
+
function iconv_fallback_utf8_iso88591($string) {
|
745 |
+
if (function_exists('utf8_decode')) {
|
746 |
+
return utf8_decode($string);
|
747 |
+
}
|
748 |
+
// utf8_decode() unavailable, use getID3()'s iconv_fallback() conversions (possibly PHP is compiled without XML support)
|
749 |
+
$newcharstring = '';
|
750 |
+
$offset = 0;
|
751 |
+
$stringlength = strlen($string);
|
752 |
+
while ($offset < $stringlength) {
|
753 |
+
if ((ord($string{$offset}) | 0x07) == 0xF7) {
|
754 |
+
// 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
|
755 |
+
$charval = ((ord($string{($offset + 0)}) & 0x07) << 18) &
|
756 |
+
((ord($string{($offset + 1)}) & 0x3F) << 12) &
|
757 |
+
((ord($string{($offset + 2)}) & 0x3F) << 6) &
|
758 |
+
(ord($string{($offset + 3)}) & 0x3F);
|
759 |
+
$offset += 4;
|
760 |
+
} elseif ((ord($string{$offset}) | 0x0F) == 0xEF) {
|
761 |
+
// 1110bbbb 10bbbbbb 10bbbbbb
|
762 |
+
$charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) &
|
763 |
+
((ord($string{($offset + 1)}) & 0x3F) << 6) &
|
764 |
+
(ord($string{($offset + 2)}) & 0x3F);
|
765 |
+
$offset += 3;
|
766 |
+
} elseif ((ord($string{$offset}) | 0x1F) == 0xDF) {
|
767 |
+
// 110bbbbb 10bbbbbb
|
768 |
+
$charval = ((ord($string{($offset + 0)}) & 0x1F) << 6) &
|
769 |
+
(ord($string{($offset + 1)}) & 0x3F);
|
770 |
+
$offset += 2;
|
771 |
+
} elseif ((ord($string{$offset}) | 0x7F) == 0x7F) {
|
772 |
+
// 0bbbbbbb
|
773 |
+
$charval = ord($string{$offset});
|
774 |
+
$offset += 1;
|
775 |
+
} else {
|
776 |
+
// error? throw some kind of warning here?
|
777 |
+
$charval = false;
|
778 |
+
$offset += 1;
|
779 |
+
}
|
780 |
+
if ($charval !== false) {
|
781 |
+
$newcharstring .= (($charval < 256) ? chr($charval) : '?');
|
782 |
+
}
|
783 |
+
}
|
784 |
+
return $newcharstring;
|
785 |
+
}
|
786 |
+
|
787 |
+
// UTF-8 => UTF-16BE
|
788 |
+
function iconv_fallback_utf8_utf16be($string, $bom=false) {
|
789 |
+
$newcharstring = '';
|
790 |
+
if ($bom) {
|
791 |
+
$newcharstring .= "\xFE\xFF";
|
792 |
+
}
|
793 |
+
$offset = 0;
|
794 |
+
$stringlength = strlen($string);
|
795 |
+
while ($offset < $stringlength) {
|
796 |
+
if ((ord($string{$offset}) | 0x07) == 0xF7) {
|
797 |
+
// 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
|
798 |
+
$charval = ((ord($string{($offset + 0)}) & 0x07) << 18) &
|
799 |
+
((ord($string{($offset + 1)}) & 0x3F) << 12) &
|
800 |
+
((ord($string{($offset + 2)}) & 0x3F) << 6) &
|
801 |
+
(ord($string{($offset + 3)}) & 0x3F);
|
802 |
+
$offset += 4;
|
803 |
+
} elseif ((ord($string{$offset}) | 0x0F) == 0xEF) {
|
804 |
+
// 1110bbbb 10bbbbbb 10bbbbbb
|
805 |
+
$charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) &
|
806 |
+
((ord($string{($offset + 1)}) & 0x3F) << 6) &
|
807 |
+
(ord($string{($offset + 2)}) & 0x3F);
|
808 |
+
$offset += 3;
|
809 |
+
} elseif ((ord($string{$offset}) | 0x1F) == 0xDF) {
|
810 |
+
// 110bbbbb 10bbbbbb
|
811 |
+
$charval = ((ord($string{($offset + 0)}) & 0x1F) << 6) &
|
812 |
+
(ord($string{($offset + 1)}) & 0x3F);
|
813 |
+
$offset += 2;
|
814 |
+
} elseif ((ord($string{$offset}) | 0x7F) == 0x7F) {
|
815 |
+
// 0bbbbbbb
|
816 |
+
$charval = ord($string{$offset});
|
817 |
+
$offset += 1;
|
818 |
+
} else {
|
819 |
+
// error? throw some kind of warning here?
|
820 |
+
$charval = false;
|
821 |
+
$offset += 1;
|
822 |
+
}
|
823 |
+
if ($charval !== false) {
|
824 |
+
$newcharstring .= (($charval < 65536) ? getid3_lib::BigEndian2String($charval, 2) : "\x00".'?');
|
825 |
+
}
|
826 |
+
}
|
827 |
+
return $newcharstring;
|
828 |
+
}
|
829 |
+
|
830 |
+
// UTF-8 => UTF-16LE
|
831 |
+
function iconv_fallback_utf8_utf16le($string, $bom=false) {
|
832 |
+
$newcharstring = '';
|
833 |
+
if ($bom) {
|
834 |
+
$newcharstring .= "\xFF\xFE";
|
835 |
+
}
|
836 |
+
$offset = 0;
|
837 |
+
$stringlength = strlen($string);
|
838 |
+
while ($offset < $stringlength) {
|
839 |
+
if ((ord($string{$offset}) | 0x07) == 0xF7) {
|
840 |
+
// 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
|
841 |
+
$charval = ((ord($string{($offset + 0)}) & 0x07) << 18) &
|
842 |
+
((ord($string{($offset + 1)}) & 0x3F) << 12) &
|
843 |
+
((ord($string{($offset + 2)}) & 0x3F) << 6) &
|
844 |
+
(ord($string{($offset + 3)}) & 0x3F);
|
845 |
+
$offset += 4;
|
846 |
+
} elseif ((ord($string{$offset}) | 0x0F) == 0xEF) {
|
847 |
+
// 1110bbbb 10bbbbbb 10bbbbbb
|
848 |
+
$charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) &
|
849 |
+
((ord($string{($offset + 1)}) & 0x3F) << 6) &
|
850 |
+
(ord($string{($offset + 2)}) & 0x3F);
|
851 |
+
$offset += 3;
|
852 |
+
} elseif ((ord($string{$offset}) | 0x1F) == 0xDF) {
|
853 |
+
// 110bbbbb 10bbbbbb
|
854 |
+
$charval = ((ord($string{($offset + 0)}) & 0x1F) << 6) &
|
855 |
+
(ord($string{($offset + 1)}) & 0x3F);
|
856 |
+
$offset += 2;
|
857 |
+
} elseif ((ord($string{$offset}) | 0x7F) == 0x7F) {
|
858 |
+
// 0bbbbbbb
|
859 |
+
$charval = ord($string{$offset});
|
860 |
+
$offset += 1;
|
861 |
+
} else {
|
862 |
+
// error? maybe throw some warning here?
|
863 |
+
$charval = false;
|
864 |
+
$offset += 1;
|
865 |
+
}
|
866 |
+
if ($charval !== false) {
|
867 |
+
$newcharstring .= (($charval < 65536) ? getid3_lib::LittleEndian2String($charval, 2) : '?'."\x00");
|
868 |
+
}
|
869 |
+
}
|
870 |
+
return $newcharstring;
|
871 |
+
}
|
872 |
+
|
873 |
+
// UTF-8 => UTF-16LE (BOM)
|
874 |
+
function iconv_fallback_utf8_utf16($string) {
|
875 |
+
return getid3_lib::iconv_fallback_utf8_utf16le($string, true);
|
876 |
+
}
|
877 |
+
|
878 |
+
// UTF-16BE => UTF-8
|
879 |
+
function iconv_fallback_utf16be_utf8($string) {
|
880 |
+
if (substr($string, 0, 2) == "\xFE\xFF") {
|
881 |
+
// strip BOM
|
882 |
+
$string = substr($string, 2);
|
883 |
+
}
|
884 |
+
$newcharstring = '';
|
885 |
+
for ($i = 0; $i < strlen($string); $i += 2) {
|
886 |
+
$charval = getid3_lib::BigEndian2Int(substr($string, $i, 2));
|
887 |
+
$newcharstring .= getid3_lib::iconv_fallback_int_utf8($charval);
|
888 |
+
}
|
889 |
+
return $newcharstring;
|
890 |
+
}
|
891 |
+
|
892 |
+
// UTF-16LE => UTF-8
|
893 |
+
function iconv_fallback_utf16le_utf8($string) {
|
894 |
+
if (substr($string, 0, 2) == "\xFF\xFE") {
|
895 |
+
// strip BOM
|
896 |
+
$string = substr($string, 2);
|
897 |
+
}
|
898 |
+
$newcharstring = '';
|
899 |
+
for ($i = 0; $i < strlen($string); $i += 2) {
|
900 |
+
$charval = getid3_lib::LittleEndian2Int(substr($string, $i, 2));
|
901 |
+
$newcharstring .= getid3_lib::iconv_fallback_int_utf8($charval);
|
902 |
+
}
|
903 |
+
return $newcharstring;
|
904 |
+
}
|
905 |
+
|
906 |
+
// UTF-16BE => ISO-8859-1
|
907 |
+
function iconv_fallback_utf16be_iso88591($string) {
|
908 |
+
if (substr($string, 0, 2) == "\xFE\xFF") {
|
909 |
+
// strip BOM
|
910 |
+
$string = substr($string, 2);
|
911 |
+
}
|
912 |
+
$newcharstring = '';
|
913 |
+
for ($i = 0; $i < strlen($string); $i += 2) {
|
914 |
+
$charval = getid3_lib::BigEndian2Int(substr($string, $i, 2));
|
915 |
+
$newcharstring .= (($charval < 256) ? chr($charval) : '?');
|
916 |
+
}
|
917 |
+
return $newcharstring;
|
918 |
+
}
|
919 |
+
|
920 |
+
// UTF-16LE => ISO-8859-1
|
921 |
+
function iconv_fallback_utf16le_iso88591($string) {
|
922 |
+
if (substr($string, 0, 2) == "\xFF\xFE") {
|
923 |
+
// strip BOM
|
924 |
+
$string = substr($string, 2);
|
925 |
+
}
|
926 |
+
$newcharstring = '';
|
927 |
+
for ($i = 0; $i < strlen($string); $i += 2) {
|
928 |
+
$charval = getid3_lib::LittleEndian2Int(substr($string, $i, 2));
|
929 |
+
$newcharstring .= (($charval < 256) ? chr($charval) : '?');
|
930 |
+
}
|
931 |
+
return $newcharstring;
|
932 |
+
}
|
933 |
+
|
934 |
+
// UTF-16 (BOM) => ISO-8859-1
|
935 |
+
function iconv_fallback_utf16_iso88591($string) {
|
936 |
+
$bom = substr($string, 0, 2);
|
937 |
+
if ($bom == "\xFE\xFF") {
|
938 |
+
return getid3_lib::iconv_fallback_utf16be_iso88591(substr($string, 2));
|
939 |
+
} elseif ($bom == "\xFF\xFE") {
|
940 |
+
return getid3_lib::iconv_fallback_utf16le_iso88591(substr($string, 2));
|
941 |
+
}
|
942 |
+
return $string;
|
943 |
+
}
|
944 |
+
|
945 |
+
// UTF-16 (BOM) => UTF-8
|
946 |
+
function iconv_fallback_utf16_utf8($string) {
|
947 |
+
$bom = substr($string, 0, 2);
|
948 |
+
if ($bom == "\xFE\xFF") {
|
949 |
+
return getid3_lib::iconv_fallback_utf16be_utf8(substr($string, 2));
|
950 |
+
} elseif ($bom == "\xFF\xFE") {
|
951 |
+
return getid3_lib::iconv_fallback_utf16le_utf8(substr($string, 2));
|
952 |
+
}
|
953 |
+
return $string;
|
954 |
+
}
|
955 |
+
|
956 |
+
function iconv_fallback($in_charset, $out_charset, $string) {
|
957 |
+
|
958 |
+
if ($in_charset == $out_charset) {
|
959 |
+
return $string;
|
960 |
+
}
|
961 |
+
|
962 |
+
// iconv() availble
|
963 |
+
if (function_exists('iconv')) {
|
964 |
+
|
965 |
+
if ($converted_string = @iconv($in_charset, $out_charset.'//TRANSLIT', $string)) {
|
966 |
+
switch ($out_charset) {
|
967 |
+
case 'ISO-8859-1':
|
968 |
+
$converted_string = rtrim($converted_string, "\x00");
|
969 |
+
break;
|
970 |
+
}
|
971 |
+
return $converted_string;
|
972 |
+
}
|
973 |
+
|
974 |
+
// iconv() may sometimes fail with "illegal character in input string" error message
|
975 |
+
// and return an empty string, but returning the unconverted string is more useful
|
976 |
+
return $string;
|
977 |
+
}
|
978 |
+
|
979 |
+
|
980 |
+
// iconv() not available
|
981 |
+
static $ConversionFunctionList = array();
|
982 |
+
if (empty($ConversionFunctionList)) {
|
983 |
+
$ConversionFunctionList['ISO-8859-1']['UTF-8'] = 'iconv_fallback_iso88591_utf8';
|
984 |
+
$ConversionFunctionList['ISO-8859-1']['UTF-16'] = 'iconv_fallback_iso88591_utf16';
|
985 |
+
$ConversionFunctionList['ISO-8859-1']['UTF-16BE'] = 'iconv_fallback_iso88591_utf16be';
|
986 |
+
$ConversionFunctionList['ISO-8859-1']['UTF-16LE'] = 'iconv_fallback_iso88591_utf16le';
|
987 |
+
$ConversionFunctionList['UTF-8']['ISO-8859-1'] = 'iconv_fallback_utf8_iso88591';
|
988 |
+
$ConversionFunctionList['UTF-8']['UTF-16'] = 'iconv_fallback_utf8_utf16';
|
989 |
+
$ConversionFunctionList['UTF-8']['UTF-16BE'] = 'iconv_fallback_utf8_utf16be';
|
990 |
+
$ConversionFunctionList['UTF-8']['UTF-16LE'] = 'iconv_fallback_utf8_utf16le';
|
991 |
+
$ConversionFunctionList['UTF-16']['ISO-8859-1'] = 'iconv_fallback_utf16_iso88591';
|
992 |
+
$ConversionFunctionList['UTF-16']['UTF-8'] = 'iconv_fallback_utf16_utf8';
|
993 |
+
$ConversionFunctionList['UTF-16LE']['ISO-8859-1'] = 'iconv_fallback_utf16le_iso88591';
|
994 |
+
$ConversionFunctionList['UTF-16LE']['UTF-8'] = 'iconv_fallback_utf16le_utf8';
|
995 |
+
$ConversionFunctionList['UTF-16BE']['ISO-8859-1'] = 'iconv_fallback_utf16be_iso88591';
|
996 |
+
$ConversionFunctionList['UTF-16BE']['UTF-8'] = 'iconv_fallback_utf16be_utf8';
|
997 |
+
}
|
998 |
+
if (isset($ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)])) {
|
999 |
+
$ConversionFunction = $ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)];
|
1000 |
+
return getid3_lib::$ConversionFunction($string);
|
1001 |
+
}
|
1002 |
+
die('PHP does not have iconv() support - cannot convert from '.$in_charset.' to '.$out_charset);
|
1003 |
+
}
|
1004 |
+
|
1005 |
+
|
1006 |
+
function MultiByteCharString2HTML($string, $charset='ISO-8859-1') {
|
1007 |
+
$HTMLstring = '';
|
1008 |
+
|
1009 |
+
switch ($charset) {
|
1010 |
+
case 'ISO-8859-1':
|
1011 |
+
case 'ISO8859-1':
|
1012 |
+
case 'ISO-8859-15':
|
1013 |
+
case 'ISO8859-15':
|
1014 |
+
case 'cp866':
|
1015 |
+
case 'ibm866':
|
1016 |
+
case '866':
|
1017 |
+
case 'cp1251':
|
1018 |
+
case 'Windows-1251':
|
1019 |
+
case 'win-1251':
|
1020 |
+
case '1251':
|
1021 |
+
case 'cp1252':
|
1022 |
+
case 'Windows-1252':
|
1023 |
+
case '1252':
|
1024 |
+
case 'KOI8-R':
|
1025 |
+
case 'koi8-ru':
|
1026 |
+
case 'koi8r':
|
1027 |
+
case 'BIG5':
|
1028 |
+
case '950':
|
1029 |
+
case 'GB2312':
|
1030 |
+
case '936':
|
1031 |
+
case 'BIG5-HKSCS':
|
1032 |
+
case 'Shift_JIS':
|
1033 |
+
case 'SJIS':
|
1034 |
+
case '932':
|
1035 |
+
case 'EUC-JP':
|
1036 |
+
case 'EUCJP':
|
1037 |
+
$HTMLstring = htmlentities($string, ENT_COMPAT, $charset);
|
1038 |
+
break;
|
1039 |
+
|
1040 |
+
case 'UTF-8':
|
1041 |
+
$strlen = strlen($string);
|
1042 |
+
for ($i = 0; $i < $strlen; $i++) {
|
1043 |
+
$char_ord_val = ord($string{$i});
|
1044 |
+
$charval = 0;
|
1045 |
+
if ($char_ord_val < 0x80) {
|
1046 |
+
$charval = $char_ord_val;
|
1047 |
+
} elseif ((($char_ord_val & 0xF0) >> 4) == 0x0F && $i+3 < $strlen) {
|
1048 |
+
$charval = (($char_ord_val & 0x07) << 18);
|
1049 |
+
$charval += ((ord($string{++$i}) & 0x3F) << 12);
|
1050 |
+
$charval += ((ord($string{++$i}) & 0x3F) << 6);
|
1051 |
+
$charval += (ord($string{++$i}) & 0x3F);
|
1052 |
+
} elseif ((($char_ord_val & 0xE0) >> 5) == 0x07 && $i+2 < $strlen) {
|
1053 |
+
$charval = (($char_ord_val & 0x0F) << 12);
|
1054 |
+
$charval += ((ord($string{++$i}) & 0x3F) << 6);
|
1055 |
+
$charval += (ord($string{++$i}) & 0x3F);
|
1056 |
+
} elseif ((($char_ord_val & 0xC0) >> 6) == 0x03 && $i+1 < $strlen) {
|
1057 |
+
$charval = (($char_ord_val & 0x1F) << 6);
|
1058 |
+
$charval += (ord($string{++$i}) & 0x3F);
|
1059 |
+
}
|
1060 |
+
if (($charval >= 32) && ($charval <= 127)) {
|
1061 |
+
$HTMLstring .= chr($charval);
|
1062 |
+
} else {
|
1063 |
+
$HTMLstring .= '&#'.$charval.';';
|
1064 |
+
}
|
1065 |
+
}
|
1066 |
+
break;
|
1067 |
+
|
1068 |
+
case 'UTF-16LE':
|
1069 |
+
for ($i = 0; $i < strlen($string); $i += 2) {
|
1070 |
+
$charval = getid3_lib::LittleEndian2Int(substr($string, $i, 2));
|
1071 |
+
if (($charval >= 32) && ($charval <= 127)) {
|
1072 |
+
$HTMLstring .= chr($charval);
|
1073 |
+
} else {
|
1074 |
+
$HTMLstring .= '&#'.$charval.';';
|
1075 |
+
}
|
1076 |
+
}
|
1077 |
+
break;
|
1078 |
+
|
1079 |
+
case 'UTF-16BE':
|
1080 |
+
for ($i = 0; $i < strlen($string); $i += 2) {
|
1081 |
+
$charval = getid3_lib::BigEndian2Int(substr($string, $i, 2));
|
1082 |
+
if (($charval >= 32) && ($charval <= 127)) {
|
1083 |
+
$HTMLstring .= chr($charval);
|
1084 |
+
} else {
|
1085 |
+
$HTMLstring .= '&#'.$charval.';';
|
1086 |
+
}
|
1087 |
+
}
|
1088 |
+
break;
|
1089 |
+
|
1090 |
+
default:
|
1091 |
+
$HTMLstring = 'ERROR: Character set "'.$charset.'" not supported in MultiByteCharString2HTML()';
|
1092 |
+
break;
|
1093 |
+
}
|
1094 |
+
return $HTMLstring;
|
1095 |
+
}
|
1096 |
+
|
1097 |
+
|
1098 |
+
|
1099 |
+
function RGADnameLookup($namecode) {
|
1100 |
+
static $RGADname = array();
|
1101 |
+
if (empty($RGADname)) {
|
1102 |
+
$RGADname[0] = 'not set';
|
1103 |
+
$RGADname[1] = 'Track Gain Adjustment';
|
1104 |
+
$RGADname[2] = 'Album Gain Adjustment';
|
1105 |
+
}
|
1106 |
+
|
1107 |
+
return (isset($RGADname[$namecode]) ? $RGADname[$namecode] : '');
|
1108 |
+
}
|
1109 |
+
|
1110 |
+
|
1111 |
+
function RGADoriginatorLookup($originatorcode) {
|
1112 |
+
static $RGADoriginator = array();
|
1113 |
+
if (empty($RGADoriginator)) {
|
1114 |
+
$RGADoriginator[0] = 'unspecified';
|
1115 |
+
$RGADoriginator[1] = 'pre-set by artist/producer/mastering engineer';
|
1116 |
+
$RGADoriginator[2] = 'set by user';
|
1117 |
+
$RGADoriginator[3] = 'determined automatically';
|
1118 |
+
}
|
1119 |
+
|
1120 |
+
return (isset($RGADoriginator[$originatorcode]) ? $RGADoriginator[$originatorcode] : '');
|
1121 |
+
}
|
1122 |
+
|
1123 |
+
|
1124 |
+
function RGADadjustmentLookup($rawadjustment, $signbit) {
|
1125 |
+
$adjustment = $rawadjustment / 10;
|
1126 |
+
if ($signbit == 1) {
|
1127 |
+
$adjustment *= -1;
|
1128 |
+
}
|
1129 |
+
return (float) $adjustment;
|
1130 |
+
}
|
1131 |
+
|
1132 |
+
|
1133 |
+
function RGADgainString($namecode, $originatorcode, $replaygain) {
|
1134 |
+
if ($replaygain < 0) {
|
1135 |
+
$signbit = '1';
|
1136 |
+
} else {
|
1137 |
+
$signbit = '0';
|
1138 |
+
}
|
1139 |
+
$storedreplaygain = intval(round($replaygain * 10));
|
1140 |
+
$gainstring = str_pad(decbin($namecode), 3, '0', STR_PAD_LEFT);
|
1141 |
+
$gainstring .= str_pad(decbin($originatorcode), 3, '0', STR_PAD_LEFT);
|
1142 |
+
$gainstring .= $signbit;
|
1143 |
+
$gainstring .= str_pad(decbin($storedreplaygain), 9, '0', STR_PAD_LEFT);
|
1144 |
+
|
1145 |
+
return $gainstring;
|
1146 |
+
}
|
1147 |
+
|
1148 |
+
function RGADamplitude2dB($amplitude) {
|
1149 |
+
return 20 * log10($amplitude);
|
1150 |
+
}
|
1151 |
+
|
1152 |
+
|
1153 |
+
function GetDataImageSize($imgData) {
|
1154 |
+
$GetDataImageSize = false;
|
1155 |
+
if ($tempfilename = tempnam('*', 'getID3')) {
|
1156 |
+
if ($tmp = @fopen($tempfilename, 'wb')) {
|
1157 |
+
fwrite($tmp, $imgData);
|
1158 |
+
fclose($tmp);
|
1159 |
+
$GetDataImageSize = @GetImageSize($tempfilename);
|
1160 |
+
}
|
1161 |
+
unlink($tempfilename);
|
1162 |
+
}
|
1163 |
+
return $GetDataImageSize;
|
1164 |
+
}
|
1165 |
+
|
1166 |
+
function ImageTypesLookup($imagetypeid) {
|
1167 |
+
static $ImageTypesLookup = array();
|
1168 |
+
if (empty($ImageTypesLookup)) {
|
1169 |
+
$ImageTypesLookup[1] = 'gif';
|
1170 |
+
$ImageTypesLookup[2] = 'jpeg';
|
1171 |
+
$ImageTypesLookup[3] = 'png';
|
1172 |
+
$ImageTypesLookup[4] = 'swf';
|
1173 |
+
$ImageTypesLookup[5] = 'psd';
|
1174 |
+
$ImageTypesLookup[6] = 'bmp';
|
1175 |
+
$ImageTypesLookup[7] = 'tiff (little-endian)';
|
1176 |
+
$ImageTypesLookup[8] = 'tiff (big-endian)';
|
1177 |
+
$ImageTypesLookup[9] = 'jpc';
|
1178 |
+
$ImageTypesLookup[10] = 'jp2';
|
1179 |
+
$ImageTypesLookup[11] = 'jpx';
|
1180 |
+
$ImageTypesLookup[12] = 'jb2';
|
1181 |
+
$ImageTypesLookup[13] = 'swc';
|
1182 |
+
$ImageTypesLookup[14] = 'iff';
|
1183 |
+
}
|
1184 |
+
return (isset($ImageTypesLookup[$imagetypeid]) ? $ImageTypesLookup[$imagetypeid] : '');
|
1185 |
+
}
|
1186 |
+
|
1187 |
+
function CopyTagsToComments(&$ThisFileInfo) {
|
1188 |
+
|
1189 |
+
// Copy all entries from ['tags'] into common ['comments']
|
1190 |
+
if (!empty($ThisFileInfo['tags'])) {
|
1191 |
+
foreach ($ThisFileInfo['tags'] as $tagtype => $tagarray) {
|
1192 |
+
foreach ($tagarray as $tagname => $tagdata) {
|
1193 |
+
foreach ($tagdata as $key => $value) {
|
1194 |
+
if (!empty($value)) {
|
1195 |
+
if (empty($ThisFileInfo['comments'][$tagname])) {
|
1196 |
+
|
1197 |
+
// fall through and append value
|
1198 |
+
|
1199 |
+
} elseif ($tagtype == 'id3v1') {
|
1200 |
+
|
1201 |
+
$newvaluelength = strlen(trim($value));
|
1202 |
+
foreach ($ThisFileInfo['comments'][$tagname] as $existingkey => $existingvalue) {
|
1203 |
+
$oldvaluelength = strlen(trim($existingvalue));
|
1204 |
+
if (($newvaluelength <= $oldvaluelength) && (substr($existingvalue, 0, $newvaluelength) == trim($value))) {
|
1205 |
+
// new value is identical but shorter-than (or equal-length to) one already in comments - skip
|
1206 |
+
break 2;
|
1207 |
+
}
|
1208 |
+
}
|
1209 |
+
|
1210 |
+
} else {
|
1211 |
+
|
1212 |
+
$newvaluelength = strlen(trim($value));
|
1213 |
+
foreach ($ThisFileInfo['comments'][$tagname] as $existingkey => $existingvalue) {
|
1214 |
+
$oldvaluelength = strlen(trim($existingvalue));
|
1215 |
+
if (($newvaluelength > $oldvaluelength) && (substr(trim($value), 0, strlen($existingvalue)) == $existingvalue)) {
|
1216 |
+
$ThisFileInfo['comments'][$tagname][$existingkey] = trim($value);
|
1217 |
+
break 2;
|
1218 |
+
}
|
1219 |
+
}
|
1220 |
+
|
1221 |
+
}
|
1222 |
+
if (empty($ThisFileInfo['comments'][$tagname]) || !in_array(trim($value), $ThisFileInfo['comments'][$tagname])) {
|
1223 |
+
$ThisFileInfo['comments'][$tagname][] = trim($value);
|
1224 |
+
}
|
1225 |
+
}
|
1226 |
+
}
|
1227 |
+
}
|
1228 |
+
}
|
1229 |
+
|
1230 |
+
// Copy to ['comments_html']
|
1231 |
+
foreach ($ThisFileInfo['comments'] as $field => $values) {
|
1232 |
+
foreach ($values as $index => $value) {
|
1233 |
+
$ThisFileInfo['comments_html'][$field][$index] = str_replace('�', '', getid3_lib::MultiByteCharString2HTML($value, $ThisFileInfo['encoding']));
|
1234 |
+
}
|
1235 |
+
}
|
1236 |
+
}
|
1237 |
+
}
|
1238 |
+
|
1239 |
+
|
1240 |
+
function EmbeddedLookup($key, $begin, $end, $file, $name) {
|
1241 |
+
|
1242 |
+
// Cached
|
1243 |
+
static $cache;
|
1244 |
+
if (isset($cache[$file][$name])) {
|
1245 |
+
return @$cache[$file][$name][$key];
|
1246 |
+
}
|
1247 |
+
|
1248 |
+
// Init
|
1249 |
+
$keylength = strlen($key);
|
1250 |
+
$line_count = $end - $begin - 7;
|
1251 |
+
|
1252 |
+
// Open php file
|
1253 |
+
$fp = fopen($file, 'r');
|
1254 |
+
|
1255 |
+
// Discard $begin lines
|
1256 |
+
for ($i = 0; $i < ($begin + 3); $i++) {
|
1257 |
+
fgets($fp, 1024);
|
1258 |
+
}
|
1259 |
+
|
1260 |
+
// Loop thru line
|
1261 |
+
while (0 < $line_count--) {
|
1262 |
+
|
1263 |
+
// Read line
|
1264 |
+
$line = ltrim(fgets($fp, 1024), "\t ");
|
1265 |
+
|
1266 |
+
// METHOD A: only cache the matching key - less memory but slower on next lookup of not-previously-looked-up key
|
1267 |
+
//$keycheck = substr($line, 0, $keylength);
|
1268 |
+
//if ($key == $keycheck) {
|
1269 |
+
// $cache[$file][$name][$keycheck] = substr($line, $keylength + 1);
|
1270 |
+
// break;
|
1271 |
+
//}
|
1272 |
+
|
1273 |
+
// METHOD B: cache all keys in this lookup - more memory but faster on next lookup of not-previously-looked-up key
|
1274 |
+
//$cache[$file][$name][substr($line, 0, $keylength)] = trim(substr($line, $keylength + 1));
|
1275 |
+
@list($ThisKey, $ThisValue) = explode("\t", $line, 2);
|
1276 |
+
$cache[$file][$name][$ThisKey] = trim($ThisValue);
|
1277 |
+
}
|
1278 |
+
|
1279 |
+
// Close and return
|
1280 |
+
fclose($fp);
|
1281 |
+
return @$cache[$file][$name][$key];
|
1282 |
+
}
|
1283 |
+
|
1284 |
+
function IncludeDependency($filename, $sourcefile, $DieOnFailure=false) {
|
1285 |
+
global $GETID3_ERRORARRAY;
|
1286 |
+
|
1287 |
+
if (file_exists($filename)) {
|
1288 |
+
if (@include_once($filename)) {
|
1289 |
+
return true;
|
1290 |
+
} else {
|
1291 |
+
$diemessage = basename($sourcefile).' depends on '.$filename.', which has errors';
|
1292 |
+
}
|
1293 |
+
} else {
|
1294 |
+
$diemessage = basename($sourcefile).' depends on '.$filename.', which is missing';
|
1295 |
+
}
|
1296 |
+
if ($DieOnFailure) {
|
1297 |
+
die($diemessage);
|
1298 |
+
} else {
|
1299 |
+
$GETID3_ERRORARRAY[] = $diemessage;
|
1300 |
+
}
|
1301 |
+
return false;
|
1302 |
+
}
|
1303 |
+
|
1304 |
+
}
|
1305 |
+
|
1306 |
+
?>
|
getid3/getid3.php
ADDED
@@ -0,0 +1,1345 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/////////////////////////////////////////////////////////////////
|
3 |
+
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
+
// available at http://getid3.sourceforge.net //
|
5 |
+
// or http://www.getid3.org //
|
6 |
+
/////////////////////////////////////////////////////////////////
|
7 |
+
// //
|
8 |
+
// Please see readme.txt for more information //
|
9 |
+
// ///
|
10 |
+
/////////////////////////////////////////////////////////////////
|
11 |
+
|
12 |
+
// Defines
|
13 |
+
define('GETID3_VERSION', '1.7.8b2');
|
14 |
+
define('GETID3_FREAD_BUFFER_SIZE', 16384); // read buffer size in bytes
|
15 |
+
|
16 |
+
|
17 |
+
|
18 |
+
class getID3
|
19 |
+
{
|
20 |
+
// public: Settings
|
21 |
+
var $encoding = 'ISO-8859-1'; // CASE SENSITIVE! - i.e. (must be supported by iconv())
|
22 |
+
// Examples: ISO-8859-1 UTF-8 UTF-16 UTF-16BE
|
23 |
+
|
24 |
+
var $encoding_id3v1 = 'ISO-8859-1'; // Should always be 'ISO-8859-1', but some tags may be written in other encodings such as 'EUC-CN'
|
25 |
+
|
26 |
+
var $tempdir = '*'; // default '*' should use system temp dir
|
27 |
+
|
28 |
+
// public: Optional tag checks - disable for speed.
|
29 |
+
var $option_tag_id3v1 = false; // Read and process ID3v1 tags
|
30 |
+
var $option_tag_id3v2 = false; // Read and process ID3v2 tags
|
31 |
+
var $option_tag_lyrics3 = false; // Read and process Lyrics3 tags
|
32 |
+
var $option_tag_apetag = false; // Read and process APE tags
|
33 |
+
var $option_tags_process = false; // Copy tags to root key 'tags' and encode to $this->encoding
|
34 |
+
var $option_tags_html = false; // Copy tags to root key 'tags_html' properly translated from various encodings to HTML entities
|
35 |
+
|
36 |
+
// public: Optional tag/comment calucations
|
37 |
+
var $option_extra_info = true; // Calculate additional info such as bitrate, channelmode etc
|
38 |
+
|
39 |
+
// public: Optional calculations
|
40 |
+
var $option_md5_data = false; // Get MD5 sum of data part - slow
|
41 |
+
var $option_md5_data_source = false; // Use MD5 of source file if availble - only FLAC and OptimFROG
|
42 |
+
var $option_sha1_data = false; // Get SHA1 sum of data part - slow
|
43 |
+
var $option_max_2gb_check = true; // Check whether file is larger than 2 Gb and thus not supported by PHP
|
44 |
+
|
45 |
+
// private
|
46 |
+
var $filename;
|
47 |
+
|
48 |
+
|
49 |
+
// public: constructor
|
50 |
+
function getID3()
|
51 |
+
{
|
52 |
+
|
53 |
+
$this->startup_error = '';
|
54 |
+
$this->startup_warning = '';
|
55 |
+
|
56 |
+
// Check for PHP version >= 4.2.0
|
57 |
+
if (phpversion() < '4.2.0') {
|
58 |
+
$this->startup_error .= 'getID3() requires PHP v4.2.0 or higher - you are running v'.phpversion();
|
59 |
+
}
|
60 |
+
|
61 |
+
// Check memory
|
62 |
+
$memory_limit = ini_get('memory_limit');
|
63 |
+
if (eregi('([0-9]+)M', $memory_limit, $matches)) {
|
64 |
+
// could be stored as "16M" rather than 16777216 for example
|
65 |
+
$memory_limit = $matches[1] * 1048576;
|
66 |
+
}
|
67 |
+
if ($memory_limit <= 0) {
|
68 |
+
// memory limits probably disabled
|
69 |
+
} elseif ($memory_limit <= 3145728) {
|
70 |
+
$this->startup_error .= 'PHP has less than 3MB available memory and will very likely run out. Increase memory_limit in php.ini';
|
71 |
+
} elseif ($memory_limit <= 12582912) {
|
72 |
+
$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';
|
73 |
+
}
|
74 |
+
|
75 |
+
// Check safe_mode off
|
76 |
+
if ((bool) ini_get('safe_mode')) {
|
77 |
+
$this->warning('WARNING: Safe mode is on, shorten support disabled, md5data/sha1data for ogg vorbis disabled, ogg vorbos/flac tag writing disabled.');
|
78 |
+
}
|
79 |
+
|
80 |
+
|
81 |
+
// define a constant rather than looking up every time it is needed
|
82 |
+
if (!defined('GETID3_OS_ISWINDOWS')) {
|
83 |
+
if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
|
84 |
+
define('GETID3_OS_ISWINDOWS', true);
|
85 |
+
} else {
|
86 |
+
define('GETID3_OS_ISWINDOWS', false);
|
87 |
+
}
|
88 |
+
}
|
89 |
+
|
90 |
+
// Get base path of getID3() - ONCE
|
91 |
+
if (!defined('GETID3_INCLUDEPATH')) {
|
92 |
+
foreach (get_included_files() as $key => $val) {
|
93 |
+
if (basename($val) == 'getid3.php') {
|
94 |
+
define('GETID3_INCLUDEPATH', dirname($val).DIRECTORY_SEPARATOR);
|
95 |
+
break;
|
96 |
+
}
|
97 |
+
}
|
98 |
+
}
|
99 |
+
|
100 |
+
// Load support library
|
101 |
+
if (!include_once(GETID3_INCLUDEPATH.'getid3.lib.php')) {
|
102 |
+
$this->startup_error .= 'getid3.lib.php is missing or corrupt';
|
103 |
+
}
|
104 |
+
|
105 |
+
|
106 |
+
// Needed for Windows only:
|
107 |
+
// Define locations of helper applications for Shorten, VorbisComment, MetaFLAC
|
108 |
+
// as well as other helper functions such as head, tail, md5sum, etc
|
109 |
+
// IMPORTANT: This path cannot have spaces in it. If neccesary, use the 8dot3 equivalent
|
110 |
+
// ie for "C:/Program Files/Apache/" put "C:/PROGRA~1/APACHE/"
|
111 |
+
// IMPORTANT: This path must include the trailing slash
|
112 |
+
if (GETID3_OS_ISWINDOWS && !defined('GETID3_HELPERAPPSDIR')) {
|
113 |
+
|
114 |
+
$helperappsdir = GETID3_INCLUDEPATH.'..'.DIRECTORY_SEPARATOR.'helperapps'; // must not have any space in this path
|
115 |
+
|
116 |
+
if (!is_dir($helperappsdir)) {
|
117 |
+
$this->startup_error .= '"'.$helperappsdir.'" cannot be defined as GETID3_HELPERAPPSDIR because it does not exist';
|
118 |
+
} elseif (strpos(realpath($helperappsdir), ' ') !== false) {
|
119 |
+
$DirPieces = explode(DIRECTORY_SEPARATOR, realpath($helperappsdir));
|
120 |
+
foreach ($DirPieces as $key => $value) {
|
121 |
+
if ((strpos($value, '.') !== false) && (strpos($value, ' ') === false)) {
|
122 |
+
if (strpos($value, '.') > 8) {
|
123 |
+
$value = substr($value, 0, 6).'~1';
|
124 |
+
}
|
125 |
+
} elseif ((strpos($value, ' ') !== false) || strlen($value) > 8) {
|
126 |
+
$value = substr($value, 0, 6).'~1';
|
127 |
+
}
|
128 |
+
$DirPieces[$key] = strtoupper($value);
|
129 |
+
}
|
130 |
+
$this->startup_error .= 'GETID3_HELPERAPPSDIR must not have any spaces in it - use 8dot3 naming convention if neccesary (on this server that would be something like "'.implode(DIRECTORY_SEPARATOR, $DirPieces).'" - NOTE: this may or may not be the actual 8.3 equivalent of "'.$helperappsdir.'", please double-check). You can run "dir /x" from the commandline to see the correct 8.3-style names.';
|
131 |
+
}
|
132 |
+
define('GETID3_HELPERAPPSDIR', realpath($helperappsdir).DIRECTORY_SEPARATOR);
|
133 |
+
}
|
134 |
+
|
135 |
+
}
|
136 |
+
|
137 |
+
|
138 |
+
// public: setOption
|
139 |
+
function setOption($optArray) {
|
140 |
+
if (!is_array($optArray) || empty($optArray)) {
|
141 |
+
return false;
|
142 |
+
}
|
143 |
+
foreach ($optArray as $opt => $val) {
|
144 |
+
if (isset($this, $opt) === false) {
|
145 |
+
continue;
|
146 |
+
}
|
147 |
+
$this->$opt = $val;
|
148 |
+
}
|
149 |
+
return true;
|
150 |
+
}
|
151 |
+
|
152 |
+
|
153 |
+
// public: analyze file - replaces GetAllFileInfo() and GetTagOnly()
|
154 |
+
function analyze($filename, $filesize=false) {
|
155 |
+
|
156 |
+
if (!empty($this->startup_error)) {
|
157 |
+
return $this->error($this->startup_error);
|
158 |
+
}
|
159 |
+
if (!empty($this->startup_warning)) {
|
160 |
+
$this->warning($this->startup_warning);
|
161 |
+
}
|
162 |
+
|
163 |
+
// init result array and set parameters
|
164 |
+
$this->info = array();
|
165 |
+
$this->info['GETID3_VERSION'] = GETID3_VERSION;
|
166 |
+
|
167 |
+
// Check encoding/iconv support
|
168 |
+
if (!function_exists('iconv') && !in_array($this->encoding, array('ISO-8859-1', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'UTF-16'))) {
|
169 |
+
$errormessage = 'iconv() support is needed for encodings other than ISO-8859-1, UTF-8, UTF-16LE, UTF16-BE, UTF-16. ';
|
170 |
+
if (GETID3_OS_ISWINDOWS) {
|
171 |
+
$errormessage .= 'PHP does not have iconv() support. Please enable php_iconv.dll in php.ini, and copy iconv.dll from c:/php/dlls to c:/windows/system32';
|
172 |
+
} else {
|
173 |
+
$errormessage .= 'PHP is not compiled with iconv() support. Please recompile with the --with-iconv switch';
|
174 |
+
}
|
175 |
+
return $this->error($errormessage);
|
176 |
+
}
|
177 |
+
|
178 |
+
// Disable magic_quotes_runtime, if neccesary
|
179 |
+
$old_magic_quotes_runtime = get_magic_quotes_runtime(); // store current setting of magic_quotes_runtime
|
180 |
+
if ($old_magic_quotes_runtime) {
|
181 |
+
set_magic_quotes_runtime(0); // turn off magic_quotes_runtime
|
182 |
+
if (get_magic_quotes_runtime()) {
|
183 |
+
return $this->error('Could not disable magic_quotes_runtime - getID3() cannot work properly with this setting enabled');
|
184 |
+
}
|
185 |
+
}
|
186 |
+
|
187 |
+
// remote files not supported
|
188 |
+
if (preg_match('/^(ht|f)tp:\/\//', $filename)) {
|
189 |
+
return $this->error('Remote files are not supported in this version of getID3() - please copy the file locally first');
|
190 |
+
}
|
191 |
+
|
192 |
+
// open local file
|
193 |
+
if (!$fp = @fopen($filename, 'rb')) {
|
194 |
+
return $this->error('Could not open file "'.$filename.'"');
|
195 |
+
}
|
196 |
+
|
197 |
+
// set parameters
|
198 |
+
if( $filesize )
|
199 |
+
$this->info['filesize'] = $filesize;
|
200 |
+
else
|
201 |
+
$this->info['filesize'] = filesize($filename);
|
202 |
+
|
203 |
+
// option_max_2gb_check
|
204 |
+
if ($this->option_max_2gb_check) {
|
205 |
+
// PHP doesn't support integers larger than 31-bit (~2GB)
|
206 |
+
// filesize() simply returns (filesize % (pow(2, 32)), no matter the actual filesize
|
207 |
+
// ftell() returns 0 if seeking to the end is beyond the range of unsigned integer
|
208 |
+
fseek($fp, 0, SEEK_END);
|
209 |
+
if ((($this->info['filesize'] != 0) && (ftell($fp) == 0)) ||
|
210 |
+
($this->info['filesize'] < 0) ||
|
211 |
+
(ftell($fp) < 0)) {
|
212 |
+
unset($this->info['filesize']);
|
213 |
+
fclose($fp);
|
214 |
+
return $this->error('File is most likely larger than 2GB and is not supported by PHP');
|
215 |
+
}
|
216 |
+
}
|
217 |
+
|
218 |
+
// set more parameters
|
219 |
+
$this->info['avdataoffset'] = 0;
|
220 |
+
$this->info['avdataend'] = $this->info['filesize'];
|
221 |
+
$this->info['fileformat'] = ''; // filled in later
|
222 |
+
$this->info['audio']['dataformat'] = ''; // filled in later, unset if not used
|
223 |
+
$this->info['video']['dataformat'] = ''; // filled in later, unset if not used
|
224 |
+
$this->info['tags'] = array(); // filled in later, unset if not used
|
225 |
+
$this->info['error'] = array(); // filled in later, unset if not used
|
226 |
+
$this->info['warning'] = array(); // filled in later, unset if not used
|
227 |
+
$this->info['comments'] = array(); // filled in later, unset if not used
|
228 |
+
$this->info['encoding'] = $this->encoding; // required by id3v2 and iso modules - can be unset at the end if desired
|
229 |
+
|
230 |
+
// set redundant parameters - might be needed in some include file
|
231 |
+
$this->info['filename'] = basename($filename);
|
232 |
+
$this->info['filepath'] = str_replace('\\', '/', realpath(dirname($filename)));
|
233 |
+
$this->info['filenamepath'] = $this->info['filepath'].'/'.$this->info['filename'];
|
234 |
+
|
235 |
+
|
236 |
+
// handle ID3v2 tag - done first - already at beginning of file
|
237 |
+
// ID3v2 detection (even if not parsing) is always done otherwise fileformat is much harder to detect
|
238 |
+
if ($this->option_tag_id3v2) {
|
239 |
+
|
240 |
+
$GETID3_ERRORARRAY = &$this->info['warning'];
|
241 |
+
if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, false)) {
|
242 |
+
$tag = new getid3_id3v2($fp, $this->info);
|
243 |
+
unset($tag);
|
244 |
+
}
|
245 |
+
|
246 |
+
} else {
|
247 |
+
|
248 |
+
fseek($fp, 0, SEEK_SET);
|
249 |
+
$header = fread($fp, 10);
|
250 |
+
if (substr($header, 0, 3) == 'ID3' && strlen($header) == 10) {
|
251 |
+
$this->info['id3v2']['header'] = true;
|
252 |
+
$this->info['id3v2']['majorversion'] = ord($header{3});
|
253 |
+
$this->info['id3v2']['minorversion'] = ord($header{4});
|
254 |
+
$this->info['id3v2']['headerlength'] = getid3_lib::BigEndian2Int(substr($header, 6, 4), 1) + 10; // length of ID3v2 tag in 10-byte header doesn't include 10-byte header length
|
255 |
+
|
256 |
+
$this->info['id3v2']['tag_offset_start'] = 0;
|
257 |
+
$this->info['id3v2']['tag_offset_end'] = $this->info['id3v2']['tag_offset_start'] + $this->info['id3v2']['headerlength'];
|
258 |
+
$this->info['avdataoffset'] = $this->info['id3v2']['tag_offset_end'];
|
259 |
+
}
|
260 |
+
|
261 |
+
}
|
262 |
+
|
263 |
+
|
264 |
+
// handle ID3v1 tag
|
265 |
+
if ($this->option_tag_id3v1) {
|
266 |
+
if (!@include_once(GETID3_INCLUDEPATH.'module.tag.id3v1.php')) {
|
267 |
+
return $this->error('module.tag.id3v1.php is missing - you may disable option_tag_id3v1.');
|
268 |
+
}
|
269 |
+
$tag = new getid3_id3v1($fp, $this->info);
|
270 |
+
unset($tag);
|
271 |
+
}
|
272 |
+
|
273 |
+
// handle APE tag
|
274 |
+
if ($this->option_tag_apetag) {
|
275 |
+
if (!@include_once(GETID3_INCLUDEPATH.'module.tag.apetag.php')) {
|
276 |
+
return $this->error('module.tag.apetag.php is missing - you may disable option_tag_apetag.');
|
277 |
+
}
|
278 |
+
$tag = new getid3_apetag($fp, $this->info);
|
279 |
+
unset($tag);
|
280 |
+
}
|
281 |
+
|
282 |
+
// handle lyrics3 tag
|
283 |
+
if ($this->option_tag_lyrics3) {
|
284 |
+
if (!@include_once(GETID3_INCLUDEPATH.'module.tag.lyrics3.php')) {
|
285 |
+
return $this->error('module.tag.lyrics3.php is missing - you may disable option_tag_lyrics3.');
|
286 |
+
}
|
287 |
+
$tag = new getid3_lyrics3($fp, $this->info);
|
288 |
+
unset($tag);
|
289 |
+
}
|
290 |
+
|
291 |
+
// read 32 kb file data
|
292 |
+
fseek($fp, $this->info['avdataoffset'], SEEK_SET);
|
293 |
+
$formattest = fread($fp, 32774);
|
294 |
+
|
295 |
+
// determine format
|
296 |
+
$determined_format = $this->GetFileFormat($formattest, $filename);
|
297 |
+
|
298 |
+
// unable to determine file format
|
299 |
+
if (!$determined_format) {
|
300 |
+
fclose($fp);
|
301 |
+
return $this->error('unable to determine file format');
|
302 |
+
}
|
303 |
+
|
304 |
+
// check for illegal ID3 tags
|
305 |
+
if (isset($determined_format['fail_id3']) && (in_array('id3v1', $this->info['tags']) || in_array('id3v2', $this->info['tags']))) {
|
306 |
+
if ($determined_format['fail_id3'] === 'ERROR') {
|
307 |
+
fclose($fp);
|
308 |
+
return $this->error('ID3 tags not allowed on this file type.');
|
309 |
+
} elseif ($determined_format['fail_id3'] === 'WARNING') {
|
310 |
+
$this->info['warning'][] = 'ID3 tags not allowed on this file type.';
|
311 |
+
}
|
312 |
+
}
|
313 |
+
|
314 |
+
// check for illegal APE tags
|
315 |
+
if (isset($determined_format['fail_ape']) && in_array('ape', $this->info['tags'])) {
|
316 |
+
if ($determined_format['fail_ape'] === 'ERROR') {
|
317 |
+
fclose($fp);
|
318 |
+
return $this->error('APE tags not allowed on this file type.');
|
319 |
+
} elseif ($determined_format['fail_ape'] === 'WARNING') {
|
320 |
+
$this->info['warning'][] = 'APE tags not allowed on this file type.';
|
321 |
+
}
|
322 |
+
}
|
323 |
+
|
324 |
+
// set mime type
|
325 |
+
$this->info['mime_type'] = $determined_format['mime_type'];
|
326 |
+
|
327 |
+
// supported format signature pattern detected, but module deleted
|
328 |
+
if (!file_exists(GETID3_INCLUDEPATH.$determined_format['include'])) {
|
329 |
+
fclose($fp);
|
330 |
+
return $this->error('Format not supported, module, '.$determined_format['include'].', was removed.');
|
331 |
+
}
|
332 |
+
|
333 |
+
// module requires iconv support
|
334 |
+
if (!function_exists('iconv') && @$determined_format['iconv_req']) {
|
335 |
+
return $this->error('iconv support is required for this module ('.$determined_format['include'].').');
|
336 |
+
}
|
337 |
+
|
338 |
+
// include module
|
339 |
+
include_once(GETID3_INCLUDEPATH.$determined_format['include']);
|
340 |
+
|
341 |
+
// instantiate module class
|
342 |
+
$class_name = 'getid3_'.$determined_format['module'];
|
343 |
+
if (!class_exists($class_name)) {
|
344 |
+
return $this->error('Format not supported, module, '.$determined_format['include'].', is corrupt.');
|
345 |
+
}
|
346 |
+
if (isset($determined_format['option'])) {
|
347 |
+
$class = new $class_name($fp, $this->info, $determined_format['option']);
|
348 |
+
} else {
|
349 |
+
$class = new $class_name($fp, $this->info);
|
350 |
+
}
|
351 |
+
unset($class);
|
352 |
+
|
353 |
+
// close file
|
354 |
+
fclose($fp);
|
355 |
+
|
356 |
+
// process all tags - copy to 'tags' and convert charsets
|
357 |
+
if ($this->option_tags_process) {
|
358 |
+
$this->HandleAllTags();
|
359 |
+
}
|
360 |
+
|
361 |
+
// perform more calculations
|
362 |
+
if ($this->option_extra_info) {
|
363 |
+
$this->ChannelsBitratePlaytimeCalculations();
|
364 |
+
$this->CalculateCompressionRatioVideo();
|
365 |
+
$this->CalculateCompressionRatioAudio();
|
366 |
+
$this->CalculateReplayGain();
|
367 |
+
$this->ProcessAudioStreams();
|
368 |
+
}
|
369 |
+
|
370 |
+
// get the MD5 sum of the audio/video portion of the file - without ID3/APE/Lyrics3/etc header/footer tags
|
371 |
+
if ($this->option_md5_data) {
|
372 |
+
// do not cald md5_data if md5_data_source is present - set by flac only - future MPC/SV8 too
|
373 |
+
if (!$this->option_md5_data_source || empty($this->info['md5_data_source'])) {
|
374 |
+
$this->getHashdata('md5');
|
375 |
+
}
|
376 |
+
}
|
377 |
+
|
378 |
+
// get the SHA1 sum of the audio/video portion of the file - without ID3/APE/Lyrics3/etc header/footer tags
|
379 |
+
if ($this->option_sha1_data) {
|
380 |
+
$this->getHashdata('sha1');
|
381 |
+
}
|
382 |
+
|
383 |
+
// remove undesired keys
|
384 |
+
$this->CleanUp();
|
385 |
+
|
386 |
+
// restore magic_quotes_runtime setting
|
387 |
+
set_magic_quotes_runtime($old_magic_quotes_runtime);
|
388 |
+
|
389 |
+
// return info array
|
390 |
+
return $this->info;
|
391 |
+
}
|
392 |
+
|
393 |
+
|
394 |
+
// private: error handling
|
395 |
+
function error($message) {
|
396 |
+
|
397 |
+
$this->CleanUp();
|
398 |
+
|
399 |
+
$this->info['error'][] = $message;
|
400 |
+
return $this->info;
|
401 |
+
}
|
402 |
+
|
403 |
+
|
404 |
+
// private: warning handling
|
405 |
+
function warning($message) {
|
406 |
+
$this->info['warning'][] = $message;
|
407 |
+
return true;
|
408 |
+
}
|
409 |
+
|
410 |
+
|
411 |
+
// private: CleanUp
|
412 |
+
function CleanUp() {
|
413 |
+
|
414 |
+
// remove possible empty keys
|
415 |
+
$AVpossibleEmptyKeys = array('dataformat', 'bits_per_sample', 'encoder_options', 'streams', 'bitrate');
|
416 |
+
foreach ($AVpossibleEmptyKeys as $dummy => $key) {
|
417 |
+
if (empty($this->info['audio'][$key]) && isset($this->info['audio'][$key])) {
|
418 |
+
unset($this->info['audio'][$key]);
|
419 |
+
}
|
420 |
+
if (empty($this->info['video'][$key]) && isset($this->info['video'][$key])) {
|
421 |
+
unset($this->info['video'][$key]);
|
422 |
+
}
|
423 |
+
}
|
424 |
+
|
425 |
+
// remove empty root keys
|
426 |
+
if (!empty($this->info)) {
|
427 |
+
foreach ($this->info as $key => $value) {
|
428 |
+
if (empty($this->info[$key]) && ($this->info[$key] !== 0) && ($this->info[$key] !== '0')) {
|
429 |
+
unset($this->info[$key]);
|
430 |
+
}
|
431 |
+
}
|
432 |
+
}
|
433 |
+
|
434 |
+
// remove meaningless entries from unknown-format files
|
435 |
+
if (empty($this->info['fileformat'])) {
|
436 |
+
if (isset($this->info['avdataoffset'])) {
|
437 |
+
unset($this->info['avdataoffset']);
|
438 |
+
}
|
439 |
+
if (isset($this->info['avdataend'])) {
|
440 |
+
unset($this->info['avdataend']);
|
441 |
+
}
|
442 |
+
}
|
443 |
+
}
|
444 |
+
|
445 |
+
|
446 |
+
// return array containing information about all supported formats
|
447 |
+
function GetFileFormatArray() {
|
448 |
+
static $format_info = array();
|
449 |
+
if (empty($format_info)) {
|
450 |
+
$format_info = array(
|
451 |
+
|
452 |
+
// Audio formats
|
453 |
+
|
454 |
+
// AC-3 - audio - Dolby AC-3 / Dolby Digital
|
455 |
+
'ac3' => array(
|
456 |
+
'pattern' => '^\x0B\x77',
|
457 |
+
'group' => 'audio',
|
458 |
+
'module' => 'ac3',
|
459 |
+
'mime_type' => 'audio/ac3',
|
460 |
+
),
|
461 |
+
|
462 |
+
// AAC - audio - Advanced Audio Coding (AAC) - ADIF format
|
463 |
+
'adif' => array(
|
464 |
+
'pattern' => '^ADIF',
|
465 |
+
'group' => 'audio',
|
466 |
+
'module' => 'aac',
|
467 |
+
'option' => 'adif',
|
468 |
+
'mime_type' => 'application/octet-stream',
|
469 |
+
'fail_ape' => 'WARNING',
|
470 |
+
),
|
471 |
+
|
472 |
+
|
473 |
+
// AAC - audio - Advanced Audio Coding (AAC) - ADTS format (very similar to MP3)
|
474 |
+
'adts' => array(
|
475 |
+
'pattern' => '^\xFF[\xF0-\xF1\xF8-\xF9]',
|
476 |
+
'group' => 'audio',
|
477 |
+
'module' => 'aac',
|
478 |
+
'option' => 'adts',
|
479 |
+
'mime_type' => 'application/octet-stream',
|
480 |
+
'fail_ape' => 'WARNING',
|
481 |
+
),
|
482 |
+
|
483 |
+
|
484 |
+
// AU - audio - NeXT/Sun AUdio (AU)
|
485 |
+
'au' => array(
|
486 |
+
'pattern' => '^\.snd',
|
487 |
+
'group' => 'audio',
|
488 |
+
'module' => 'au',
|
489 |
+
'mime_type' => 'audio/basic',
|
490 |
+
),
|
491 |
+
|
492 |
+
// AVR - audio - Audio Visual Research
|
493 |
+
'avr' => array(
|
494 |
+
'pattern' => '^2BIT',
|
495 |
+
'group' => 'audio',
|
496 |
+
'module' => 'avr',
|
497 |
+
'mime_type' => 'application/octet-stream',
|
498 |
+
),
|
499 |
+
|
500 |
+
// BONK - audio - Bonk v0.9+
|
501 |
+
'bonk' => array(
|
502 |
+
'pattern' => '^\x00(BONK|INFO|META| ID3)',
|
503 |
+
'group' => 'audio',
|
504 |
+
'module' => 'bonk',
|
505 |
+
'mime_type' => 'audio/xmms-bonk',
|
506 |
+
),
|
507 |
+
|
508 |
+
// DTS - audio - Dolby Theatre System
|
509 |
+
'dts' => array(
|
510 |
+
'pattern' => '^\x7F\xFE\x80\x01',
|
511 |
+
'group' => 'audio',
|
512 |
+
'module' => 'dts',
|
513 |
+
'mime_type' => 'audio/dts',
|
514 |
+
),
|
515 |
+
|
516 |
+
// FLAC - audio - Free Lossless Audio Codec
|
517 |
+
'flac' => array(
|
518 |
+
'pattern' => '^fLaC',
|
519 |
+
'group' => 'audio',
|
520 |
+
'module' => 'flac',
|
521 |
+
'mime_type' => 'audio/x-flac',
|
522 |
+
),
|
523 |
+
|
524 |
+
// LA - audio - Lossless Audio (LA)
|
525 |
+
'la' => array(
|
526 |
+
'pattern' => '^LA0[2-4]',
|
527 |
+
'group' => 'audio',
|
528 |
+
'module' => 'la',
|
529 |
+
'mime_type' => 'application/octet-stream',
|
530 |
+
),
|
531 |
+
|
532 |
+
// LPAC - audio - Lossless Predictive Audio Compression (LPAC)
|
533 |
+
'lpac' => array(
|
534 |
+
'pattern' => '^LPAC',
|
535 |
+
'group' => 'audio',
|
536 |
+
'module' => 'lpac',
|
537 |
+
'mime_type' => 'application/octet-stream',
|
538 |
+
),
|
539 |
+
|
540 |
+
// MIDI - audio - MIDI (Musical Instrument Digital Interface)
|
541 |
+
'midi' => array(
|
542 |
+
'pattern' => '^MThd',
|
543 |
+
'group' => 'audio',
|
544 |
+
'module' => 'midi',
|
545 |
+
'mime_type' => 'audio/midi',
|
546 |
+
),
|
547 |
+
|
548 |
+
// MAC - audio - Monkey's Audio Compressor
|
549 |
+
'mac' => array(
|
550 |
+
'pattern' => '^MAC ',
|
551 |
+
'group' => 'audio',
|
552 |
+
'module' => 'monkey',
|
553 |
+
'mime_type' => 'application/octet-stream',
|
554 |
+
),
|
555 |
+
|
556 |
+
// MOD - audio - MODule (assorted sub-formats)
|
557 |
+
'mod' => array(
|
558 |
+
'pattern' => '^.{1080}(M.K.|[5-9]CHN|[1-3][0-9]CH)',
|
559 |
+
'group' => 'audio',
|
560 |
+
'module' => 'mod',
|
561 |
+
'option' => 'mod',
|
562 |
+
'mime_type' => 'audio/mod',
|
563 |
+
),
|
564 |
+
|
565 |
+
// MOD - audio - MODule (Impulse Tracker)
|
566 |
+
'it' => array(
|
567 |
+
'pattern' => '^IMPM',
|
568 |
+
'group' => 'audio',
|
569 |
+
'module' => 'mod',
|
570 |
+
'option' => 'it',
|
571 |
+
'mime_type' => 'audio/it',
|
572 |
+
),
|
573 |
+
|
574 |
+
// MOD - audio - MODule (eXtended Module, various sub-formats)
|
575 |
+
'xm' => array(
|
576 |
+
'pattern' => '^Extended Module',
|
577 |
+
'group' => 'audio',
|
578 |
+
'module' => 'mod',
|
579 |
+
'option' => 'xm',
|
580 |
+
'mime_type' => 'audio/xm',
|
581 |
+
),
|
582 |
+
|
583 |
+
// MOD - audio - MODule (ScreamTracker)
|
584 |
+
's3m' => array(
|
585 |
+
'pattern' => '^.{44}SCRM',
|
586 |
+
'group' => 'audio',
|
587 |
+
'module' => 'mod',
|
588 |
+
'option' => 's3m',
|
589 |
+
'mime_type' => 'audio/s3m',
|
590 |
+
),
|
591 |
+
|
592 |
+
// MPC - audio - Musepack / MPEGplus
|
593 |
+
'mpc' => array(
|
594 |
+
'pattern' => '^(MP\+|[\x00\x01\x10\x11\x40\x41\x50\x51\x80\x81\x90\x91\xC0\xC1\xD0\xD1][\x20-37][\x00\x20\x40\x60\x80\xA0\xC0\xE0])',
|
595 |
+
'group' => 'audio',
|
596 |
+
'module' => 'mpc',
|
597 |
+
'mime_type' => 'audio/x-musepack',
|
598 |
+
),
|
599 |
+
|
600 |
+
// MP3 - audio - MPEG-audio Layer 3 (very similar to AAC-ADTS)
|
601 |
+
'mp3' => array(
|
602 |
+
'pattern' => '^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\xEB]',
|
603 |
+
'group' => 'audio',
|
604 |
+
'module' => 'mp3',
|
605 |
+
'mime_type' => 'audio/mpeg',
|
606 |
+
),
|
607 |
+
|
608 |
+
// OFR - audio - OptimFROG
|
609 |
+
'ofr' => array(
|
610 |
+
'pattern' => '^(\*RIFF|OFR)',
|
611 |
+
'group' => 'audio',
|
612 |
+
'module' => 'optimfrog',
|
613 |
+
'mime_type' => 'application/octet-stream',
|
614 |
+
),
|
615 |
+
|
616 |
+
// RKAU - audio - RKive AUdio compressor
|
617 |
+
'rkau' => array(
|
618 |
+
'pattern' => '^RKA',
|
619 |
+
'group' => 'audio',
|
620 |
+
'module' => 'rkau',
|
621 |
+
'mime_type' => 'application/octet-stream',
|
622 |
+
),
|
623 |
+
|
624 |
+
// SHN - audio - Shorten
|
625 |
+
'shn' => array(
|
626 |
+
'pattern' => '^ajkg',
|
627 |
+
'group' => 'audio',
|
628 |
+
'module' => 'shorten',
|
629 |
+
'mime_type' => 'audio/xmms-shn',
|
630 |
+
'fail_id3' => 'ERROR',
|
631 |
+
'fail_ape' => 'ERROR',
|
632 |
+
),
|
633 |
+
|
634 |
+
// TTA - audio - TTA Lossless Audio Compressor (http://tta.corecodec.org)
|
635 |
+
'tta' => array(
|
636 |
+
'pattern' => '^TTA', // could also be '^TTA(\x01|\x02|\x03|2|1)'
|
637 |
+
'group' => 'audio',
|
638 |
+
'module' => 'tta',
|
639 |
+
'mime_type' => 'application/octet-stream',
|
640 |
+
),
|
641 |
+
|
642 |
+
// VOC - audio - Creative Voice (VOC)
|
643 |
+
'voc' => array(
|
644 |
+
'pattern' => '^Creative Voice File',
|
645 |
+
'group' => 'audio',
|
646 |
+
'module' => 'voc',
|
647 |
+
'mime_type' => 'audio/voc',
|
648 |
+
),
|
649 |
+
|
650 |
+
// VQF - audio - transform-domain weighted interleave Vector Quantization Format (VQF)
|
651 |
+
'vqf' => array(
|
652 |
+
'pattern' => '^TWIN',
|
653 |
+
'group' => 'audio',
|
654 |
+
'module' => 'vqf',
|
655 |
+
'mime_type' => 'application/octet-stream',
|
656 |
+
),
|
657 |
+
|
658 |
+
// WV - audio - WavPack (v4.0+)
|
659 |
+
'wv' => array(
|
660 |
+
'pattern' => '^wvpk',
|
661 |
+
'group' => 'audio',
|
662 |
+
'module' => 'wavpack',
|
663 |
+
'mime_type' => 'application/octet-stream',
|
664 |
+
),
|
665 |
+
|
666 |
+
|
667 |
+
// Audio-Video formats
|
668 |
+
|
669 |
+
// ASF - audio/video - Advanced Streaming Format, Windows Media Video, Windows Media Audio
|
670 |
+
'asf' => array(
|
671 |
+
'pattern' => '^\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C',
|
672 |
+
'group' => 'audio-video',
|
673 |
+
'module' => 'asf',
|
674 |
+
'mime_type' => 'video/x-ms-asf',
|
675 |
+
'iconv_req' => false,
|
676 |
+
),
|
677 |
+
|
678 |
+
// BINK - audio/video - Bink / Smacker
|
679 |
+
'bink' => array(
|
680 |
+
'pattern' => '^(BIK|SMK)',
|
681 |
+
'group' => 'audio-video',
|
682 |
+
'module' => 'bink',
|
683 |
+
'mime_type' => 'application/octet-stream',
|
684 |
+
),
|
685 |
+
|
686 |
+
// FLV - audio/video - FLash Video
|
687 |
+
'flv' => array(
|
688 |
+
'pattern' => '^FLV\x01',
|
689 |
+
'group' => 'audio-video',
|
690 |
+
'module' => 'flv',
|
691 |
+
'mime_type' => 'video/x-flv',
|
692 |
+
),
|
693 |
+
|
694 |
+
// MKAV - audio/video - Mastroka
|
695 |
+
'matroska' => array(
|
696 |
+
'pattern' => '^\x1A\x45\xDF\xA3',
|
697 |
+
'group' => 'audio-video',
|
698 |
+
'module' => 'matroska',
|
699 |
+
'mime_type' => 'application/octet-stream',
|
700 |
+
),
|
701 |
+
|
702 |
+
// MPEG - audio/video - MPEG (Moving Pictures Experts Group)
|
703 |
+
'mpeg' => array(
|
704 |
+
'pattern' => '^\x00\x00\x01(\xBA|\xB3)',
|
705 |
+
'group' => 'audio-video',
|
706 |
+
'module' => 'mpeg',
|
707 |
+
'mime_type' => 'video/mpeg',
|
708 |
+
),
|
709 |
+
|
710 |
+
// NSV - audio/video - Nullsoft Streaming Video (NSV)
|
711 |
+
'nsv' => array(
|
712 |
+
'pattern' => '^NSV[sf]',
|
713 |
+
'group' => 'audio-video',
|
714 |
+
'module' => 'nsv',
|
715 |
+
'mime_type' => 'application/octet-stream',
|
716 |
+
),
|
717 |
+
|
718 |
+
// Ogg - audio/video - Ogg (Ogg-Vorbis, Ogg-FLAC, Speex, Ogg-Theora(*), Ogg-Tarkin(*))
|
719 |
+
'ogg' => array(
|
720 |
+
'pattern' => '^OggS',
|
721 |
+
'group' => 'audio',
|
722 |
+
'module' => 'ogg',
|
723 |
+
'mime_type' => 'application/ogg',
|
724 |
+
'fail_id3' => 'WARNING',
|
725 |
+
'fail_ape' => 'WARNING',
|
726 |
+
),
|
727 |
+
|
728 |
+
// QT - audio/video - Quicktime
|
729 |
+
'quicktime' => array(
|
730 |
+
'pattern' => '^.{4}(cmov|free|ftyp|mdat|moov|pnot|skip|wide)',
|
731 |
+
'group' => 'audio-video',
|
732 |
+
'module' => 'quicktime',
|
733 |
+
'mime_type' => 'video/quicktime',
|
734 |
+
),
|
735 |
+
|
736 |
+
// 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)
|
737 |
+
'riff' => array(
|
738 |
+
'pattern' => '^(RIFF|SDSS|FORM)',
|
739 |
+
'group' => 'audio-video',
|
740 |
+
'module' => 'riff',
|
741 |
+
'mime_type' => 'audio/x-wave',
|
742 |
+
'fail_ape' => 'WARNING',
|
743 |
+
),
|
744 |
+
|
745 |
+
// Real - audio/video - RealAudio, RealVideo
|
746 |
+
'real' => array(
|
747 |
+
'pattern' => '^(\.RMF|.ra)',
|
748 |
+
'group' => 'audio-video',
|
749 |
+
'module' => 'real',
|
750 |
+
'mime_type' => 'audio/x-realaudio',
|
751 |
+
),
|
752 |
+
|
753 |
+
// SWF - audio/video - ShockWave Flash
|
754 |
+
'swf' => array(
|
755 |
+
'pattern' => '^(F|C)WS',
|
756 |
+
'group' => 'audio-video',
|
757 |
+
'module' => 'swf',
|
758 |
+
'mime_type' => 'application/x-shockwave-flash',
|
759 |
+
),
|
760 |
+
|
761 |
+
|
762 |
+
// Still-Image formats
|
763 |
+
|
764 |
+
// BMP - still image - Bitmap (Windows, OS/2; uncompressed, RLE8, RLE4)
|
765 |
+
'bmp' => array(
|
766 |
+
'pattern' => '^BM',
|
767 |
+
'group' => 'graphic',
|
768 |
+
'module' => 'bmp',
|
769 |
+
'mime_type' => 'image/bmp',
|
770 |
+
'fail_id3' => 'ERROR',
|
771 |
+
'fail_ape' => 'ERROR',
|
772 |
+
),
|
773 |
+
|
774 |
+
// GIF - still image - Graphics Interchange Format
|
775 |
+
'gif' => array(
|
776 |
+
'pattern' => '^GIF',
|
777 |
+
'group' => 'graphic',
|
778 |
+
'module' => 'gif',
|
779 |
+
'mime_type' => 'image/gif',
|
780 |
+
'fail_id3' => 'ERROR',
|
781 |
+
'fail_ape' => 'ERROR',
|
782 |
+
),
|
783 |
+
|
784 |
+
// JPEG - still image - Joint Photographic Experts Group (JPEG)
|
785 |
+
'jpg' => array(
|
786 |
+
'pattern' => '^\xFF\xD8\xFF',
|
787 |
+
'group' => 'graphic',
|
788 |
+
'module' => 'jpg',
|
789 |
+
'mime_type' => 'image/jpeg',
|
790 |
+
'fail_id3' => 'ERROR',
|
791 |
+
'fail_ape' => 'ERROR',
|
792 |
+
),
|
793 |
+
|
794 |
+
// PCD - still image - Kodak Photo CD
|
795 |
+
'pcd' => array(
|
796 |
+
'pattern' => '^.{2048}PCD_IPI\x00',
|
797 |
+
'group' => 'graphic',
|
798 |
+
'module' => 'pcd',
|
799 |
+
'mime_type' => 'image/x-photo-cd',
|
800 |
+
'fail_id3' => 'ERROR',
|
801 |
+
'fail_ape' => 'ERROR',
|
802 |
+
),
|
803 |
+
|
804 |
+
|
805 |
+
// PNG - still image - Portable Network Graphics (PNG)
|
806 |
+
'png' => array(
|
807 |
+
'pattern' => '^\x89\x50\x4E\x47\x0D\x0A\x1A\x0A',
|
808 |
+
'group' => 'graphic',
|
809 |
+
'module' => 'png',
|
810 |
+
'mime_type' => 'image/png',
|
811 |
+
'fail_id3' => 'ERROR',
|
812 |
+
'fail_ape' => 'ERROR',
|
813 |
+
),
|
814 |
+
|
815 |
+
|
816 |
+
// SVG - still image - Scalable Vector Graphics (SVG)
|
817 |
+
'svg' => array(
|
818 |
+
'pattern' => '<!DOCTYPE svg PUBLIC ',
|
819 |
+
'group' => 'graphic',
|
820 |
+
'module' => 'svg',
|
821 |
+
'mime_type' => 'image/svg+xml',
|
822 |
+
'fail_id3' => 'ERROR',
|
823 |
+
'fail_ape' => 'ERROR',
|
824 |
+
),
|
825 |
+
|
826 |
+
|
827 |
+
// TIFF - still image - Tagged Information File Format (TIFF)
|
828 |
+
'tiff' => array(
|
829 |
+
'pattern' => '^(II\x2A\x00|MM\x00\x2A)',
|
830 |
+
'group' => 'graphic',
|
831 |
+
'module' => 'tiff',
|
832 |
+
'mime_type' => 'image/tiff',
|
833 |
+
'fail_id3' => 'ERROR',
|
834 |
+
'fail_ape' => 'ERROR',
|
835 |
+
),
|
836 |
+
|
837 |
+
|
838 |
+
// Data formats
|
839 |
+
|
840 |
+
// ISO - data - International Standards Organization (ISO) CD-ROM Image
|
841 |
+
'iso' => array(
|
842 |
+
'pattern' => '^.{32769}CD001',
|
843 |
+
'group' => 'misc',
|
844 |
+
'module' => 'iso',
|
845 |
+
'mime_type' => 'application/octet-stream',
|
846 |
+
'fail_id3' => 'ERROR',
|
847 |
+
'fail_ape' => 'ERROR',
|
848 |
+
'iconv_req' => false,
|
849 |
+
),
|
850 |
+
|
851 |
+
// RAR - data - RAR compressed data
|
852 |
+
'rar' => array(
|
853 |
+
'pattern' => '^Rar\!',
|
854 |
+
'group' => 'archive',
|
855 |
+
'module' => 'rar',
|
856 |
+
'mime_type' => 'application/octet-stream',
|
857 |
+
'fail_id3' => 'ERROR',
|
858 |
+
'fail_ape' => 'ERROR',
|
859 |
+
),
|
860 |
+
|
861 |
+
// SZIP - audio/data - SZIP compressed data
|
862 |
+
'szip' => array(
|
863 |
+
'pattern' => '^SZ\x0A\x04',
|
864 |
+
'group' => 'archive',
|
865 |
+
'module' => 'szip',
|
866 |
+
'mime_type' => 'application/octet-stream',
|
867 |
+
'fail_id3' => 'ERROR',
|
868 |
+
'fail_ape' => 'ERROR',
|
869 |
+
),
|
870 |
+
|
871 |
+
// TAR - data - TAR compressed data
|
872 |
+
'tar' => array(
|
873 |
+
'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}',
|
874 |
+
'group' => 'archive',
|
875 |
+
'module' => 'tar',
|
876 |
+
'mime_type' => 'application/x-tar',
|
877 |
+
'fail_id3' => 'ERROR',
|
878 |
+
'fail_ape' => 'ERROR',
|
879 |
+
),
|
880 |
+
|
881 |
+
// GZIP - data - GZIP compressed data
|
882 |
+
'gz' => array(
|
883 |
+
'pattern' => '^\x1F\x8B\x08',
|
884 |
+
'group' => 'archive',
|
885 |
+
'module' => 'gzip',
|
886 |
+
'mime_type' => 'application/x-gzip',
|
887 |
+
'fail_id3' => 'ERROR',
|
888 |
+
'fail_ape' => 'ERROR',
|
889 |
+
),
|
890 |
+
|
891 |
+
// ZIP - data - ZIP compressed data
|
892 |
+
'zip' => array(
|
893 |
+
'pattern' => '^PK\x03\x04',
|
894 |
+
'group' => 'archive',
|
895 |
+
'module' => 'zip',
|
896 |
+
'mime_type' => 'application/zip',
|
897 |
+
'fail_id3' => 'ERROR',
|
898 |
+
'fail_ape' => 'ERROR',
|
899 |
+
),
|
900 |
+
|
901 |
+
|
902 |
+
// Misc other formats
|
903 |
+
|
904 |
+
// PAR2 - data - Parity Volume Set Specification 2.0
|
905 |
+
'par2' => array (
|
906 |
+
'pattern' => '^PAR2\x00PKT',
|
907 |
+
'group' => 'misc',
|
908 |
+
'module' => 'par2',
|
909 |
+
'mime_type' => 'application/octet-stream',
|
910 |
+
'fail_id3' => 'ERROR',
|
911 |
+
'fail_ape' => 'ERROR',
|
912 |
+
),
|
913 |
+
|
914 |
+
// PDF - data - Portable Document Format
|
915 |
+
'pdf' => array(
|
916 |
+
'pattern' => '^\x25PDF',
|
917 |
+
'group' => 'misc',
|
918 |
+
'module' => 'pdf',
|
919 |
+
'mime_type' => 'application/pdf',
|
920 |
+
'fail_id3' => 'ERROR',
|
921 |
+
'fail_ape' => 'ERROR',
|
922 |
+
),
|
923 |
+
|
924 |
+
// MSOFFICE - data - ZIP compressed data
|
925 |
+
'msoffice' => array(
|
926 |
+
'pattern' => '^\xD0\xCF\x11\xE0', // D0CF11E == DOCFILE == Microsoft Office Document
|
927 |
+
'group' => 'misc',
|
928 |
+
'module' => 'msoffice',
|
929 |
+
'mime_type' => 'application/octet-stream',
|
930 |
+
'fail_id3' => 'ERROR',
|
931 |
+
'fail_ape' => 'ERROR',
|
932 |
+
),
|
933 |
+
);
|
934 |
+
}
|
935 |
+
|
936 |
+
return $format_info;
|
937 |
+
}
|
938 |
+
|
939 |
+
|
940 |
+
|
941 |
+
function GetFileFormat(&$filedata, $filename='') {
|
942 |
+
// this function will determine the format of a file based on usually
|
943 |
+
// the first 2-4 bytes of the file (8 bytes for PNG, 16 bytes for JPG,
|
944 |
+
// and in the case of ISO CD image, 6 bytes offset 32kb from the start
|
945 |
+
// of the file).
|
946 |
+
|
947 |
+
// Identify file format - loop through $format_info and detect with reg expr
|
948 |
+
foreach ($this->GetFileFormatArray() as $format_name => $info) {
|
949 |
+
// Using preg_match() instead of ereg() - much faster
|
950 |
+
// The /s switch on preg_match() forces preg_match() NOT to treat
|
951 |
+
// newline (0x0A) characters as special chars but do a binary match
|
952 |
+
if (preg_match('/'.$info['pattern'].'/s', $filedata)) {
|
953 |
+
$info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php';
|
954 |
+
return $info;
|
955 |
+
}
|
956 |
+
}
|
957 |
+
|
958 |
+
|
959 |
+
if (preg_match('/\.mp[123a]$/i', $filename)) {
|
960 |
+
// Too many mp3 encoders on the market put gabage in front of mpeg files
|
961 |
+
// use assume format on these if format detection failed
|
962 |
+
$GetFileFormatArray = $this->GetFileFormatArray();
|
963 |
+
$info = $GetFileFormatArray['mp3'];
|
964 |
+
$info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php';
|
965 |
+
return $info;
|
966 |
+
}
|
967 |
+
|
968 |
+
return false;
|
969 |
+
}
|
970 |
+
|
971 |
+
|
972 |
+
// converts array to $encoding charset from $this->encoding
|
973 |
+
function CharConvert(&$array, $encoding) {
|
974 |
+
|
975 |
+
// identical encoding - end here
|
976 |
+
if ($encoding == $this->encoding) {
|
977 |
+
return;
|
978 |
+
}
|
979 |
+
|
980 |
+
// loop thru array
|
981 |
+
foreach ($array as $key => $value) {
|
982 |
+
|
983 |
+
// go recursive
|
984 |
+
if (is_array($value)) {
|
985 |
+
$this->CharConvert($array[$key], $encoding);
|
986 |
+
}
|
987 |
+
|
988 |
+
// convert string
|
989 |
+
elseif (is_string($value)) {
|
990 |
+
$array[$key] = trim(getid3_lib::iconv_fallback($encoding, $this->encoding, $value));
|
991 |
+
}
|
992 |
+
}
|
993 |
+
}
|
994 |
+
|
995 |
+
|
996 |
+
function HandleAllTags() {
|
997 |
+
|
998 |
+
// key name => array (tag name, character encoding)
|
999 |
+
static $tags;
|
1000 |
+
if (empty($tags)) {
|
1001 |
+
$tags = array(
|
1002 |
+
'asf' => array('asf' , 'UTF-16LE'),
|
1003 |
+
'midi' => array('midi' , 'ISO-8859-1'),
|
1004 |
+
'nsv' => array('nsv' , 'ISO-8859-1'),
|
1005 |
+
'ogg' => array('vorbiscomment' , 'UTF-8'),
|
1006 |
+
'png' => array('png' , 'UTF-8'),
|
1007 |
+
'tiff' => array('tiff' , 'ISO-8859-1'),
|
1008 |
+
'quicktime' => array('quicktime' , 'ISO-8859-1'),
|
1009 |
+
'real' => array('real' , 'ISO-8859-1'),
|
1010 |
+
'vqf' => array('vqf' , 'ISO-8859-1'),
|
1011 |
+
'zip' => array('zip' , 'ISO-8859-1'),
|
1012 |
+
'riff' => array('riff' , 'ISO-8859-1'),
|
1013 |
+
'lyrics3' => array('lyrics3' , 'ISO-8859-1'),
|
1014 |
+
'id3v1' => array('id3v1' , $this->encoding_id3v1),
|
1015 |
+
'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
|
1016 |
+
'ape' => array('ape' , 'UTF-8')
|
1017 |
+
);
|
1018 |
+
}
|
1019 |
+
|
1020 |
+
// loop thru comments array
|
1021 |
+
foreach ($tags as $comment_name => $tagname_encoding_array) {
|
1022 |
+
list($tag_name, $encoding) = $tagname_encoding_array;
|
1023 |
+
|
1024 |
+
// fill in default encoding type if not already present
|
1025 |
+
if (isset($this->info[$comment_name]) && !isset($this->info[$comment_name]['encoding'])) {
|
1026 |
+
$this->info[$comment_name]['encoding'] = $encoding;
|
1027 |
+
}
|
1028 |
+
|
1029 |
+
// copy comments if key name set
|
1030 |
+
if (!empty($this->info[$comment_name]['comments'])) {
|
1031 |
+
|
1032 |
+
foreach ($this->info[$comment_name]['comments'] as $tag_key => $valuearray) {
|
1033 |
+
foreach ($valuearray as $key => $value) {
|
1034 |
+
if (strlen(trim($value)) > 0) {
|
1035 |
+
$this->info['tags'][trim($tag_name)][trim($tag_key)][] = $value; // do not trim!! Unicode characters will get mangled if trailing nulls are removed!
|
1036 |
+
}
|
1037 |
+
}
|
1038 |
+
}
|
1039 |
+
|
1040 |
+
if (!isset($this->info['tags'][$tag_name])) {
|
1041 |
+
// comments are set but contain nothing but empty strings, so skip
|
1042 |
+
continue;
|
1043 |
+
}
|
1044 |
+
|
1045 |
+
if ($this->option_tags_html) {
|
1046 |
+
foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) {
|
1047 |
+
foreach ($valuearray as $key => $value) {
|
1048 |
+
if (is_string($value)) {
|
1049 |
+
//$this->info['tags_html'][$tag_name][$tag_key][$key] = getid3_lib::MultiByteCharString2HTML($value, $encoding);
|
1050 |
+
$this->info['tags_html'][$tag_name][$tag_key][$key] = str_replace('�', '', getid3_lib::MultiByteCharString2HTML($value, $encoding));
|
1051 |
+
} else {
|
1052 |
+
$this->info['tags_html'][$tag_name][$tag_key][$key] = $value;
|
1053 |
+
}
|
1054 |
+
}
|
1055 |
+
}
|
1056 |
+
}
|
1057 |
+
|
1058 |
+
$this->CharConvert($this->info['tags'][$tag_name], $encoding); // only copy gets converted!
|
1059 |
+
}
|
1060 |
+
|
1061 |
+
}
|
1062 |
+
return true;
|
1063 |
+
}
|
1064 |
+
|
1065 |
+
|
1066 |
+
function getHashdata($algorithm) {
|
1067 |
+
switch ($algorithm) {
|
1068 |
+
case 'md5':
|
1069 |
+
case 'sha1':
|
1070 |
+
break;
|
1071 |
+
|
1072 |
+
default:
|
1073 |
+
return $this->error('bad algorithm "'.$algorithm.'" in getHashdata()');
|
1074 |
+
break;
|
1075 |
+
}
|
1076 |
+
|
1077 |
+
if ((@$this->info['fileformat'] == 'ogg') && (@$this->info['audio']['dataformat'] == 'vorbis')) {
|
1078 |
+
|
1079 |
+
// We cannot get an identical md5_data value for Ogg files where the comments
|
1080 |
+
// span more than 1 Ogg page (compared to the same audio data with smaller
|
1081 |
+
// comments) using the normal getID3() method of MD5'ing the data between the
|
1082 |
+
// end of the comments and the end of the file (minus any trailing tags),
|
1083 |
+
// because the page sequence numbers of the pages that the audio data is on
|
1084 |
+
// do not match. Under normal circumstances, where comments are smaller than
|
1085 |
+
// the nominal 4-8kB page size, then this is not a problem, but if there are
|
1086 |
+
// very large comments, the only way around it is to strip off the comment
|
1087 |
+
// tags with vorbiscomment and MD5 that file.
|
1088 |
+
// This procedure must be applied to ALL Ogg files, not just the ones with
|
1089 |
+
// comments larger than 1 page, because the below method simply MD5's the
|
1090 |
+
// whole file with the comments stripped, not just the portion after the
|
1091 |
+
// comments block (which is the standard getID3() method.
|
1092 |
+
|
1093 |
+
// The above-mentioned problem of comments spanning multiple pages and changing
|
1094 |
+
// page sequence numbers likely happens for OggSpeex and OggFLAC as well, but
|
1095 |
+
// currently vorbiscomment only works on OggVorbis files.
|
1096 |
+
|
1097 |
+
if ((bool) ini_get('safe_mode')) {
|
1098 |
+
|
1099 |
+
$this->info['warning'][] = 'Failed making system call to vorbiscomment.exe - '.$algorithm.'_data is incorrect - error returned: PHP running in Safe Mode (backtick operator not available)';
|
1100 |
+
$this->info[$algorithm.'_data'] = false;
|
1101 |
+
|
1102 |
+
} else {
|
1103 |
+
|
1104 |
+
// Prevent user from aborting script
|
1105 |
+
$old_abort = ignore_user_abort(true);
|
1106 |
+
|
1107 |
+
// Create empty file
|
1108 |
+
$empty = tempnam('*', 'getID3');
|
1109 |
+
touch($empty);
|
1110 |
+
|
1111 |
+
|
1112 |
+
// Use vorbiscomment to make temp file without comments
|
1113 |
+
$temp = tempnam('*', 'getID3');
|
1114 |
+
$file = $this->info['filenamepath'];
|
1115 |
+
|
1116 |
+
if (GETID3_OS_ISWINDOWS) {
|
1117 |
+
|
1118 |
+
if (file_exists(GETID3_HELPERAPPSDIR.'vorbiscomment.exe')) {
|
1119 |
+
|
1120 |
+
$commandline = '"'.GETID3_HELPERAPPSDIR.'vorbiscomment.exe" -w -c "'.$empty.'" "'.$file.'" "'.$temp.'"';
|
1121 |
+
$VorbisCommentError = `$commandline`;
|
1122 |
+
|
1123 |
+
} else {
|
1124 |
+
|
1125 |
+
$VorbisCommentError = 'vorbiscomment.exe not found in '.GETID3_HELPERAPPSDIR;
|
1126 |
+
|
1127 |
+
}
|
1128 |
+
|
1129 |
+
} else {
|
1130 |
+
|
1131 |
+
$commandline = 'vorbiscomment -w -c "'.$empty.'" "'.$file.'" "'.$temp.'" 2>&1';
|
1132 |
+
$commandline = 'vorbiscomment -w -c '.escapeshellarg($empty).' '.escapeshellarg($file).' '.escapeshellarg($temp).' 2>&1';
|
1133 |
+
$VorbisCommentError = `$commandline`;
|
1134 |
+
|
1135 |
+
}
|
1136 |
+
|
1137 |
+
if (!empty($VorbisCommentError)) {
|
1138 |
+
|
1139 |
+
$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;
|
1140 |
+
$this->info[$algorithm.'_data'] = false;
|
1141 |
+
|
1142 |
+
} else {
|
1143 |
+
|
1144 |
+
// Get hash of newly created file
|
1145 |
+
switch ($algorithm) {
|
1146 |
+
case 'md5':
|
1147 |
+
$this->info[$algorithm.'_data'] = getid3_lib::md5_file($temp);
|
1148 |
+
break;
|
1149 |
+
|
1150 |
+
case 'sha1':
|
1151 |
+
$this->info[$algorithm.'_data'] = getid3_lib::sha1_file($temp);
|
1152 |
+
break;
|
1153 |
+
}
|
1154 |
+
}
|
1155 |
+
|
1156 |
+
// Clean up
|
1157 |
+
unlink($empty);
|
1158 |
+
unlink($temp);
|
1159 |
+
|
1160 |
+
// Reset abort setting
|
1161 |
+
ignore_user_abort($old_abort);
|
1162 |
+
|
1163 |
+
}
|
1164 |
+
|
1165 |
+
} else {
|
1166 |
+
|
1167 |
+
if (!empty($this->info['avdataoffset']) || (isset($this->info['avdataend']) && ($this->info['avdataend'] < $this->info['filesize']))) {
|
1168 |
+
|
1169 |
+
// get hash from part of file
|
1170 |
+
$this->info[$algorithm.'_data'] = getid3_lib::hash_data($this->info['filenamepath'], $this->info['avdataoffset'], $this->info['avdataend'], $algorithm);
|
1171 |
+
|
1172 |
+
} else {
|
1173 |
+
|
1174 |
+
// get hash from whole file
|
1175 |
+
switch ($algorithm) {
|
1176 |
+
case 'md5':
|
1177 |
+
$this->info[$algorithm.'_data'] = getid3_lib::md5_file($this->info['filenamepath']);
|
1178 |
+
break;
|
1179 |
+
|
1180 |
+
case 'sha1':
|
1181 |
+
$this->info[$algorithm.'_data'] = getid3_lib::sha1_file($this->info['filenamepath']);
|
1182 |
+
break;
|
1183 |
+
}
|
1184 |
+
}
|
1185 |
+
|
1186 |
+
}
|
1187 |
+
return true;
|
1188 |
+
}
|
1189 |
+
|
1190 |
+
|
1191 |
+
function ChannelsBitratePlaytimeCalculations() {
|
1192 |
+
|
1193 |
+
// set channelmode on audio
|
1194 |
+
if (@$this->info['audio']['channels'] == '1') {
|
1195 |
+
$this->info['audio']['channelmode'] = 'mono';
|
1196 |
+
} elseif (@$this->info['audio']['channels'] == '2') {
|
1197 |
+
$this->info['audio']['channelmode'] = 'stereo';
|
1198 |
+
}
|
1199 |
+
|
1200 |
+
// Calculate combined bitrate - audio + video
|
1201 |
+
$CombinedBitrate = 0;
|
1202 |
+
$CombinedBitrate += (isset($this->info['audio']['bitrate']) ? $this->info['audio']['bitrate'] : 0);
|
1203 |
+
$CombinedBitrate += (isset($this->info['video']['bitrate']) ? $this->info['video']['bitrate'] : 0);
|
1204 |
+
if (($CombinedBitrate > 0) && empty($this->info['bitrate'])) {
|
1205 |
+
$this->info['bitrate'] = $CombinedBitrate;
|
1206 |
+
}
|
1207 |
+
//if ((isset($this->info['video']) && !isset($this->info['video']['bitrate'])) || (isset($this->info['audio']) && !isset($this->info['audio']['bitrate']))) {
|
1208 |
+
// // for example, VBR MPEG video files cannot determine video bitrate:
|
1209 |
+
// // should not set overall bitrate and playtime from audio bitrate only
|
1210 |
+
// unset($this->info['bitrate']);
|
1211 |
+
//}
|
1212 |
+
|
1213 |
+
// video bitrate undetermined, but calculable
|
1214 |
+
if (isset($this->info['video']['dataformat']) && $this->info['video']['dataformat'] && (!isset($this->info['video']['bitrate']) || ($this->info['video']['bitrate'] == 0))) {
|
1215 |
+
// if video bitrate not set
|
1216 |
+
if (isset($this->info['audio']['bitrate']) && ($this->info['audio']['bitrate'] > 0) && ($this->info['audio']['bitrate'] == $this->info['bitrate'])) {
|
1217 |
+
// AND if audio bitrate is set to same as overall bitrate
|
1218 |
+
if (isset($this->info['playtime_seconds']) && ($this->info['playtime_seconds'] > 0)) {
|
1219 |
+
// AND if playtime is set
|
1220 |
+
if (isset($this->info['avdataend']) && isset($this->info['avdataoffset'])) {
|
1221 |
+
// AND if AV data offset start/end is known
|
1222 |
+
// THEN we can calculate the video bitrate
|
1223 |
+
$this->info['bitrate'] = round((($this->info['avdataend'] - $this->info['avdataoffset']) * 8) / $this->info['playtime_seconds']);
|
1224 |
+
$this->info['video']['bitrate'] = $this->info['bitrate'] - $this->info['audio']['bitrate'];
|
1225 |
+
}
|
1226 |
+
}
|
1227 |
+
}
|
1228 |
+
}
|
1229 |
+
|
1230 |
+
if (!isset($this->info['playtime_seconds']) && !empty($this->info['bitrate'])) {
|
1231 |
+
$this->info['playtime_seconds'] = (($this->info['avdataend'] - $this->info['avdataoffset']) * 8) / $this->info['bitrate'];
|
1232 |
+
}
|
1233 |
+
|
1234 |
+
// Set playtime string
|
1235 |
+
if (!empty($this->info['playtime_seconds']) && empty($this->info['playtime_string'])) {
|
1236 |
+
$this->info['playtime_string'] = getid3_lib::PlaytimeString($this->info['playtime_seconds']);
|
1237 |
+
}
|
1238 |
+
}
|
1239 |
+
|
1240 |
+
|
1241 |
+
function CalculateCompressionRatioVideo() {
|
1242 |
+
if (empty($this->info['video'])) {
|
1243 |
+
return false;
|
1244 |
+
}
|
1245 |
+
if (empty($this->info['video']['resolution_x']) || empty($this->info['video']['resolution_y'])) {
|
1246 |
+
return false;
|
1247 |
+
}
|
1248 |
+
if (empty($this->info['video']['bits_per_sample'])) {
|
1249 |
+
return false;
|
1250 |
+
}
|
1251 |
+
|
1252 |
+
switch ($this->info['video']['dataformat']) {
|
1253 |
+
case 'bmp':
|
1254 |
+
case 'gif':
|
1255 |
+
case 'jpeg':
|
1256 |
+
case 'jpg':
|
1257 |
+
case 'png':
|
1258 |
+
case 'tiff':
|
1259 |
+
$FrameRate = 1;
|
1260 |
+
$PlaytimeSeconds = 1;
|
1261 |
+
$BitrateCompressed = $this->info['filesize'] * 8;
|
1262 |
+
break;
|
1263 |
+
|
1264 |
+
default:
|
1265 |
+
if (!empty($this->info['video']['frame_rate'])) {
|
1266 |
+
$FrameRate = $this->info['video']['frame_rate'];
|
1267 |
+
} else {
|
1268 |
+
return false;
|
1269 |
+
}
|
1270 |
+
if (!empty($this->info['playtime_seconds'])) {
|
1271 |
+
$PlaytimeSeconds = $this->info['playtime_seconds'];
|
1272 |
+
} else {
|
1273 |
+
return false;
|
1274 |
+
}
|
1275 |
+
if (!empty($this->info['video']['bitrate'])) {
|
1276 |
+
$BitrateCompressed = $this->info['video']['bitrate'];
|
1277 |
+
} else {
|
1278 |
+
return false;
|
1279 |
+
}
|
1280 |
+
break;
|
1281 |
+
}
|
1282 |
+
$BitrateUncompressed = $this->info['video']['resolution_x'] * $this->info['video']['resolution_y'] * $this->info['video']['bits_per_sample'] * $FrameRate;
|
1283 |
+
|
1284 |
+
$this->info['video']['compression_ratio'] = $BitrateCompressed / $BitrateUncompressed;
|
1285 |
+
return true;
|
1286 |
+
}
|
1287 |
+
|
1288 |
+
|
1289 |
+
function CalculateCompressionRatioAudio() {
|
1290 |
+
if (empty($this->info['audio']['bitrate']) || empty($this->info['audio']['channels']) || empty($this->info['audio']['sample_rate'])) {
|
1291 |
+
return false;
|
1292 |
+
}
|
1293 |
+
$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));
|
1294 |
+
|
1295 |
+
if (!empty($this->info['audio']['streams'])) {
|
1296 |
+
foreach ($this->info['audio']['streams'] as $streamnumber => $streamdata) {
|
1297 |
+
if (!empty($streamdata['bitrate']) && !empty($streamdata['channels']) && !empty($streamdata['sample_rate'])) {
|
1298 |
+
$this->info['audio']['streams'][$streamnumber]['compression_ratio'] = $streamdata['bitrate'] / ($streamdata['channels'] * $streamdata['sample_rate'] * (!empty($streamdata['bits_per_sample']) ? $streamdata['bits_per_sample'] : 16));
|
1299 |
+
}
|
1300 |
+
}
|
1301 |
+
}
|
1302 |
+
return true;
|
1303 |
+
}
|
1304 |
+
|
1305 |
+
|
1306 |
+
function CalculateReplayGain() {
|
1307 |
+
if (isset($this->info['replay_gain'])) {
|
1308 |
+
$this->info['replay_gain']['reference_volume'] = 89;
|
1309 |
+
if (isset($this->info['replay_gain']['track']['adjustment'])) {
|
1310 |
+
$this->info['replay_gain']['track']['volume'] = $this->info['replay_gain']['reference_volume'] - $this->info['replay_gain']['track']['adjustment'];
|
1311 |
+
}
|
1312 |
+
if (isset($this->info['replay_gain']['album']['adjustment'])) {
|
1313 |
+
$this->info['replay_gain']['album']['volume'] = $this->info['replay_gain']['reference_volume'] - $this->info['replay_gain']['album']['adjustment'];
|
1314 |
+
}
|
1315 |
+
|
1316 |
+
if (isset($this->info['replay_gain']['track']['peak'])) {
|
1317 |
+
$this->info['replay_gain']['track']['max_noclip_gain'] = 0 - getid3_lib::RGADamplitude2dB($this->info['replay_gain']['track']['peak']);
|
1318 |
+
}
|
1319 |
+
if (isset($this->info['replay_gain']['album']['peak'])) {
|
1320 |
+
$this->info['replay_gain']['album']['max_noclip_gain'] = 0 - getid3_lib::RGADamplitude2dB($this->info['replay_gain']['album']['peak']);
|
1321 |
+
}
|
1322 |
+
}
|
1323 |
+
return true;
|
1324 |
+
}
|
1325 |
+
|
1326 |
+
function ProcessAudioStreams() {
|
1327 |
+
if (!empty($this->info['audio']['bitrate']) || !empty($this->info['audio']['channels']) || !empty($this->info['audio']['sample_rate'])) {
|
1328 |
+
if (!isset($this->info['audio']['streams'])) {
|
1329 |
+
foreach ($this->info['audio'] as $key => $value) {
|
1330 |
+
if ($key != 'streams') {
|
1331 |
+
$this->info['audio']['streams'][0][$key] = $value;
|
1332 |
+
}
|
1333 |
+
}
|
1334 |
+
}
|
1335 |
+
}
|
1336 |
+
return true;
|
1337 |
+
}
|
1338 |
+
|
1339 |
+
function getid3_tempnam() {
|
1340 |
+
return tempnam($this->tempdir, 'gI3');
|
1341 |
+
}
|
1342 |
+
|
1343 |
+
}
|
1344 |
+
|
1345 |
+
?>
|
getid3/module.audio.mp3.php
ADDED
@@ -0,0 +1,1932 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/////////////////////////////////////////////////////////////////
|
3 |
+
/// getID3() by James Heinrich <info@getid3.org> //
|
4 |
+
// available at http://getid3.sourceforge.net //
|
5 |
+
// or http://www.getid3.org //
|
6 |
+
/////////////////////////////////////////////////////////////////
|
7 |
+
// See readme.txt for more details //
|
8 |
+
/////////////////////////////////////////////////////////////////
|
9 |
+
// //
|
10 |
+
// module.audio.mp3.php //
|
11 |
+
// module for analyzing MP3 files //
|
12 |
+
// dependencies: NONE //
|
13 |
+
// ///
|
14 |
+
/////////////////////////////////////////////////////////////////
|
15 |
+
|
16 |
+
|
17 |
+
// number of frames to scan to determine if MPEG-audio sequence is valid
|
18 |
+
// Lower this number to 5-20 for faster scanning
|
19 |
+
// Increase this number to 50+ for most accurate detection of valid VBR/CBR
|
20 |
+
// mpeg-audio streams
|
21 |
+
define('GETID3_MP3_VALID_CHECK_FRAMES', 35);
|
22 |
+
|
23 |
+
|
24 |
+
class getid3_mp3
|
25 |
+
{
|
26 |
+
|
27 |
+
var $allow_bruteforce = false; // forces getID3() to scan the file byte-by-byte and log all the valid audio frame headers - extremely slow, unrecommended, but may provide data from otherwise-unusuable files
|
28 |
+
|
29 |
+
function getid3_mp3(&$fd, &$ThisFileInfo) {
|
30 |
+
|
31 |
+
if (!$this->getOnlyMPEGaudioInfo($fd, $ThisFileInfo, $ThisFileInfo['avdataoffset'])) {
|
32 |
+
if ($this->allow_bruteforce) {
|
33 |
+
$ThisFileInfo['error'][] = 'Rescanning file in BruteForce mode';
|
34 |
+
$this->getOnlyMPEGaudioInfoBruteForce($fd, $ThisFileInfo);
|
35 |
+
}
|
36 |
+
}
|
37 |
+
|
38 |
+
|
39 |
+
if (isset($ThisFileInfo['mpeg']['audio']['bitrate_mode'])) {
|
40 |
+
$ThisFileInfo['audio']['bitrate_mode'] = strtolower($ThisFileInfo['mpeg']['audio']['bitrate_mode']);
|
41 |
+
}
|
42 |
+
|
43 |
+
if (((isset($ThisFileInfo['id3v2']['headerlength']) && ($ThisFileInfo['avdataoffset'] > $ThisFileInfo['id3v2']['headerlength'])) || (!isset($ThisFileInfo['id3v2']) && ($ThisFileInfo['avdataoffset'] > 0)))) {
|
44 |
+
|
45 |
+
$synchoffsetwarning = 'Unknown data before synch ';
|
46 |
+
if (isset($ThisFileInfo['id3v2']['headerlength'])) {
|
47 |
+
$synchoffsetwarning .= '(ID3v2 header ends at '.$ThisFileInfo['id3v2']['headerlength'].', then '.($ThisFileInfo['avdataoffset'] - $ThisFileInfo['id3v2']['headerlength']).' bytes garbage, ';
|
48 |
+
} else {
|
49 |
+
$synchoffsetwarning .= '(should be at beginning of file, ';
|
50 |
+
}
|
51 |
+
$synchoffsetwarning .= 'synch detected at '.$ThisFileInfo['avdataoffset'].')';
|
52 |
+
if ($ThisFileInfo['audio']['bitrate_mode'] == 'cbr') {
|
53 |
+
|
54 |
+
if (!empty($ThisFileInfo['id3v2']['headerlength']) && (($ThisFileInfo['avdataoffset'] - $ThisFileInfo['id3v2']['headerlength']) == $ThisFileInfo['mpeg']['audio']['framelength'])) {
|
55 |
+
|
56 |
+
$synchoffsetwarning .= '. This is a known problem with some versions of LAME (3.90-3.92) DLL in CBR mode.';
|
57 |
+
$ThisFileInfo['audio']['codec'] = 'LAME';
|
58 |
+
$CurrentDataLAMEversionString = 'LAME3.';
|
59 |
+
|
60 |
+
} elseif (empty($ThisFileInfo['id3v2']['headerlength']) && ($ThisFileInfo['avdataoffset'] == $ThisFileInfo['mpeg']['audio']['framelength'])) {
|
61 |
+
|
62 |
+
$synchoffsetwarning .= '. This is a known problem with some versions of LAME (3.90 - 3.92) DLL in CBR mode.';
|
63 |
+
$ThisFileInfo['audio']['codec'] = 'LAME';
|
64 |
+
$CurrentDataLAMEversionString = 'LAME3.';
|
65 |
+
|
66 |
+
}
|
67 |
+
|
68 |
+
}
|
69 |
+
$ThisFileInfo['warning'][] = $synchoffsetwarning;
|
70 |
+
|
71 |
+
}
|
72 |
+
|
73 |
+
if (isset($ThisFileInfo['mpeg']['audio']['LAME'])) {
|
74 |
+
$ThisFileInfo['audio']['codec'] = 'LAME';
|
75 |
+
if (!empty($ThisFileInfo['mpeg']['audio']['LAME']['long_version'])) {
|
76 |
+
$ThisFileInfo['audio']['encoder'] = rtrim($ThisFileInfo['mpeg']['audio']['LAME']['long_version'], "\x00");
|
77 |
+
} elseif (!empty($ThisFileInfo['mpeg']['audio']['LAME']['short_version'])) {
|
78 |
+
$ThisFileInfo['audio']['encoder'] = rtrim($ThisFileInfo['mpeg']['audio']['LAME']['short_version'], "\x00");
|
79 |
+
}
|
80 |
+
}
|
81 |
+
|
82 |
+
$CurrentDataLAMEversionString = (!empty($CurrentDataLAMEversionString) ? $CurrentDataLAMEversionString : @$ThisFileInfo['audio']['encoder']);
|
83 |
+
if (!empty($CurrentDataLAMEversionString) && (substr($CurrentDataLAMEversionString, 0, 6) == 'LAME3.') && !preg_match('[0-9\)]', substr($CurrentDataLAMEversionString, -1))) {
|
84 |
+
// a version number of LAME that does not end with a number like "LAME3.92"
|
85 |
+
// or with a closing parenthesis like "LAME3.88 (alpha)"
|
86 |
+
// or a version of LAME with the LAMEtag-not-filled-in-DLL-mode bug (3.90-3.92)
|
87 |
+
|
88 |
+
// not sure what the actual last frame length will be, but will be less than or equal to 1441
|
89 |
+
$PossiblyLongerLAMEversion_FrameLength = 1441;
|
90 |
+
|
91 |
+
// Not sure what version of LAME this is - look in padding of last frame for longer version string
|
92 |
+
$PossibleLAMEversionStringOffset = $ThisFileInfo['avdataend'] - $PossiblyLongerLAMEversion_FrameLength;
|
93 |
+
fseek($fd, $PossibleLAMEversionStringOffset);
|
94 |
+
$PossiblyLongerLAMEversion_Data = fread($fd, $PossiblyLongerLAMEversion_FrameLength);
|
95 |
+
switch (substr($CurrentDataLAMEversionString, -1)) {
|
96 |
+
case 'a':
|
97 |
+
case 'b':
|
98 |
+
// "LAME3.94a" will have a longer version string of "LAME3.94 (alpha)" for example
|
99 |
+
// need to trim off "a" to match longer string
|
100 |
+
$CurrentDataLAMEversionString = substr($CurrentDataLAMEversionString, 0, -1);
|
101 |
+
break;
|
102 |
+
}
|
103 |
+
if (($PossiblyLongerLAMEversion_String = strstr($PossiblyLongerLAMEversion_Data, $CurrentDataLAMEversionString)) !== false) {
|
104 |
+
if (substr($PossiblyLongerLAMEversion_String, 0, strlen($CurrentDataLAMEversionString)) == $CurrentDataLAMEversionString) {
|
105 |
+
$PossiblyLongerLAMEversion_NewString = substr($PossiblyLongerLAMEversion_String, 0, strspn($PossiblyLongerLAMEversion_String, 'LAME0123456789., (abcdefghijklmnopqrstuvwxyzJFSOND)')); //"LAME3.90.3" "LAME3.87 (beta 1, Sep 27 2000)" "LAME3.88 (beta)"
|
106 |
+
if (strlen($PossiblyLongerLAMEversion_NewString) > strlen(@$ThisFileInfo['audio']['encoder'])) {
|
107 |
+
$ThisFileInfo['audio']['encoder'] = $PossiblyLongerLAMEversion_NewString;
|
108 |
+
}
|
109 |
+
}
|
110 |
+
}
|
111 |
+
}
|
112 |
+
if (!empty($ThisFileInfo['audio']['encoder'])) {
|
113 |
+
$ThisFileInfo['audio']['encoder'] = rtrim($ThisFileInfo['audio']['encoder'], "\x00 ");
|
114 |
+
}
|
115 |
+
|
116 |
+
switch (@$ThisFileInfo['mpeg']['audio']['layer']) {
|
117 |
+
case 1:
|
118 |
+
case 2:
|
119 |
+
$ThisFileInfo['audio']['dataformat'] = 'mp'.$ThisFileInfo['mpeg']['audio']['layer'];
|
120 |
+
break;
|
121 |
+
}
|
122 |
+
if ($ThisFileInfo['fileformat'] == 'mp3') {
|
123 |
+
switch ($ThisFileInfo['audio']['dataformat']) {
|
124 |
+
case 'mp1':
|
125 |
+
case 'mp2':
|
126 |
+
case 'mp3':
|
127 |
+
$ThisFileInfo['fileformat'] = $ThisFileInfo['audio']['dataformat'];
|
128 |
+
break;
|
129 |
+
|
130 |
+
default:
|
131 |
+
$ThisFileInfo['warning'][] = 'Expecting [audio][dataformat] to be mp1/mp2/mp3 when fileformat == mp3, [audio][dataformat] actually "'.$ThisFileInfo['audio']['dataformat'].'"';
|
132 |
+
break;
|
133 |
+
}
|
134 |
+
}
|
135 |
+
|
136 |
+
if (empty($ThisFileInfo['fileformat'])) {
|
137 |
+
unset($ThisFileInfo['fileformat']);
|
138 |
+
unset($ThisFileInfo['audio']['bitrate_mode']);
|
139 |
+
unset($ThisFileInfo['avdataoffset']);
|
140 |
+
unset($ThisFileInfo['avdataend']);
|
141 |
+
return false;
|
142 |
+
}
|
143 |
+
|
144 |
+
$ThisFileInfo['mime_type'] = 'audio/mpeg';
|
145 |
+
$ThisFileInfo['audio']['lossless'] = false;
|
146 |
+
|
147 |
+
// Calculate playtime
|
148 |
+
if (!isset($ThisFileInfo['playtime_seconds']) && isset($ThisFileInfo['audio']['bitrate']) && ($ThisFileInfo['audio']['bitrate'] > 0)) {
|
149 |
+
$ThisFileInfo['playtime_seconds'] = ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8 / $ThisFileInfo['audio']['bitrate'];
|
150 |
+
}
|
151 |
+
|
152 |
+
$ThisFileInfo['audio']['encoder_options'] = $this->GuessEncoderOptions($ThisFileInfo);
|
153 |
+
|
154 |
+
return true;
|
155 |
+
}
|
156 |
+
|
157 |
+
|
158 |
+
function GuessEncoderOptions(&$ThisFileInfo) {
|
159 |
+
// shortcuts
|
160 |
+
if (!empty($ThisFileInfo['mpeg']['audio'])) {
|
161 |
+
$thisfile_mpeg_audio = &$ThisFileInfo['mpeg']['audio'];
|
162 |
+
if (!empty($thisfile_mpeg_audio['LAME'])) {
|
163 |
+
$thisfile_mpeg_audio_lame = &$thisfile_mpeg_audio['LAME'];
|
164 |
+
}
|
165 |
+
}
|
166 |
+
|
167 |
+
$encoder_options = '';
|
168 |
+
static $NamedPresetBitrates = array(16, 24, 40, 56, 112, 128, 160, 192, 256);
|
169 |
+
|
170 |
+
if ((@$thisfile_mpeg_audio['VBR_method'] == 'Fraunhofer') && !empty($thisfile_mpeg_audio['VBR_quality'])) {
|
171 |
+
|
172 |
+
$encoder_options = 'VBR q'.$thisfile_mpeg_audio['VBR_quality'];
|
173 |
+
|
174 |
+
} elseif (!empty($thisfile_mpeg_audio_lame['preset_used']) && (!in_array($thisfile_mpeg_audio_lame['preset_used_id'], $NamedPresetBitrates))) {
|
175 |
+
|
176 |
+
$encoder_options = $thisfile_mpeg_audio_lame['preset_used'];
|
177 |
+
|
178 |
+
} elseif (!empty($thisfile_mpeg_audio_lame['vbr_quality'])) {
|
179 |
+
|
180 |
+
static $KnownEncoderValues = array();
|
181 |
+
if (empty($KnownEncoderValues)) {
|
182 |
+
|
183 |
+
//$KnownEncoderValues[abrbitrate_minbitrate][vbr_quality][raw_vbr_method][raw_noise_shaping][raw_stereo_mode][ath_type][lowpass_frequency] = 'preset name';
|
184 |
+
$KnownEncoderValues[0xFF][58][1][1][3][2][20500] = '--alt-preset insane'; // 3.90, 3.90.1, 3.92
|
185 |
+
$KnownEncoderValues[0xFF][58][1][1][3][2][20600] = '--alt-preset insane'; // 3.90.2, 3.90.3, 3.91
|
186 |
+
$KnownEncoderValues[0xFF][57][1][1][3][4][20500] = '--alt-preset insane'; // 3.94, 3.95
|
187 |
+
$KnownEncoderValues['**'][78][3][2][3][2][19500] = '--alt-preset extreme'; // 3.90, 3.90.1, 3.92
|
188 |
+
$KnownEncoderValues['**'][78][3][2][3][2][19600] = '--alt-preset extreme'; // 3.90.2, 3.91
|
189 |
+
$KnownEncoderValues['**'][78][3][1][3][2][19600] = '--alt-preset extreme'; // 3.90.3
|
190 |
+
$KnownEncoderValues['**'][78][4][2][3][2][19500] = '--alt-preset fast extreme'; // 3.90, 3.90.1, 3.92
|
191 |
+
$KnownEncoderValues['**'][78][4][2][3][2][19600] = '--alt-preset fast extreme'; // 3.90.2, 3.90.3, 3.91
|
192 |
+
$KnownEncoderValues['**'][78][3][2][3][4][19000] = '--alt-preset standard'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92
|
193 |
+
$KnownEncoderValues['**'][78][3][1][3][4][19000] = '--alt-preset standard'; // 3.90.3
|
194 |
+
$KnownEncoderValues['**'][78][4][2][3][4][19000] = '--alt-preset fast standard'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92
|
195 |
+
$KnownEncoderValues['**'][78][4][1][3][4][19000] = '--alt-preset fast standard'; // 3.90.3
|
196 |
+
$KnownEncoderValues['**'][88][4][1][3][3][19500] = '--r3mix'; // 3.90, 3.90.1, 3.92
|
197 |
+
$KnownEncoderValues['**'][88][4][1][3][3][19600] = '--r3mix'; // 3.90.2, 3.90.3, 3.91
|
198 |
+
$KnownEncoderValues['**'][67][4][1][3][4][18000] = '--r3mix'; // 3.94, 3.95
|
199 |
+
$KnownEncoderValues['**'][68][3][2][3][4][18000] = '--alt-preset medium'; // 3.90.3
|
200 |
+
$KnownEncoderValues['**'][68][4][2][3][4][18000] = '--alt-preset fast medium'; // 3.90.3
|
201 |
+
|
202 |
+
$KnownEncoderValues[0xFF][99][1][1][1][2][0] = '--preset studio'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92
|
203 |
+
$KnownEncoderValues[0xFF][58][2][1][3][2][20600] = '--preset studio'; // 3.90.3, 3.93.1
|
204 |
+
$KnownEncoderValues[0xFF][58][2][1][3][2][20500] = '--preset studio'; // 3.93
|
205 |
+
$KnownEncoderValues[0xFF][57][2][1][3][4][20500] = '--preset studio'; // 3.94, 3.95
|
206 |
+
$KnownEncoderValues[0xC0][88][1][1][1][2][0] = '--preset cd'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92
|
207 |
+
$KnownEncoderValues[0xC0][58][2][2][3][2][19600] = '--preset cd'; // 3.90.3, 3.93.1
|
208 |
+
$KnownEncoderValues[0xC0][58][2][2][3][2][19500] = '--preset cd'; // 3.93
|
209 |
+
$KnownEncoderValues[0xC0][57][2][1][3][4][19500] = '--preset cd'; // 3.94, 3.95
|
210 |
+
$KnownEncoderValues[0xA0][78][1][1][3][2][18000] = '--preset hifi'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92
|
211 |
+
$KnownEncoderValues[0xA0][58][2][2][3][2][18000] = '--preset hifi'; // 3.90.3, 3.93, 3.93.1
|
212 |
+
$KnownEncoderValues[0xA0][57][2][1][3][4][18000] = '--preset hifi'; // 3.94, 3.95
|
213 |
+
$KnownEncoderValues[0x80][67][1][1][3][2][18000] = '--preset tape'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92
|
214 |
+
$KnownEncoderValues[0x80][67][1][1][3][2][15000] = '--preset radio'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92
|
215 |
+
$KnownEncoderValues[0x70][67][1][1][3][2][15000] = '--preset fm'; // 3.90, 3.90.1, 3.90.2, 3.91, 3.92
|
216 |
+
$KnownEncoderValues[0x70][58][2][2][3][2][16000] = '--preset tape/radio/fm'; // 3.90.3, 3.93, 3.93.1
|
217 |
+
$KnownEncoderValues[0x70][57][2][1][3][4][16000] = '--preset tape/radio/fm'; // 3.94, 3.95
|
218 |
+
$KnownEncoderValues[0x38][58][2][2][0][2][10000] = '--preset voice'; // 3.90.3, 3.93, 3.93.1
|
219 |
+
$KnownEncoderValues[0x38][57][2][1][0][4][15000] = '--preset voice'; // 3.94, 3.95
|
220 |
+
$KnownEncoderValues[0x38][57][2][1][0][4][16000] = '--preset voice'; // 3.94a14
|
221 |
+
$KnownEncoderValues[0x28][65][1][1][0][2][7500] = '--preset mw-us'; // 3.90, 3.90.1, 3.92
|
222 |
+
$KnownEncoderValues[0x28][65][1][1][0][2][7600] = '--preset mw-us'; // 3.90.2, 3.91
|
223 |
+
$KnownEncoderValues[0x28][58][2][2][0][2][7000] = '--preset mw-us'; // 3.90.3, 3.93, 3.93.1
|
224 |
+
$KnownEncoderValues[0x28][57][2][1][0][4][10500] = '--preset mw-us'; // 3.94, 3.95
|
225 |
+
$KnownEncoderValues[0x28][57][2][1][0][4][11200] = '--preset mw-us'; // 3.94a14
|
226 |
+
$KnownEncoderValues[0x28][57][2][1][0][4][8800] = '--preset mw-us'; // 3.94a15
|
227 |
+
$KnownEncoderValues[0x18][58][2][2][0][2][4000] = '--preset phon+/lw/mw-eu/sw'; // 3.90.3, 3.93.1
|
228 |
+
$KnownEncoderValues[0x18][58][2][2][0][2][3900] = '--preset phon+/lw/mw-eu/sw'; // 3.93
|
229 |
+
$KnownEncoderValues[0x18][57][2][1][0][4][5900] = '--preset phon+/lw/mw-eu/sw'; // 3.94, 3.95
|
230 |
+
$KnownEncoderValues[0x18][57][2][1][0][4][6200] = '--preset phon+/lw/mw-eu/sw'; // 3.94a14
|
231 |
+
$KnownEncoderValues[0x18][57][2][1][0][4][3200] = '--preset phon+/lw/mw-eu/sw'; // 3.94a15
|
232 |
+
$KnownEncoderValues[0x10][58][2][2][0][2][3800] = '--preset phone'; // 3.90.3, 3.93.1
|
233 |
+
$KnownEncoderValues[0x10][58][2][2][0][2][3700] = '--preset phone'; // 3.93
|
234 |
+
$KnownEncoderValues[0x10][57][2][1][0][4][5600] = '--preset phone'; // 3.94, 3.95
|
235 |
+
}
|
236 |
+
|
237 |
+
if (isset($KnownEncoderValues[$thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate']][$thisfile_mpeg_audio_lame['vbr_quality']][$thisfile_mpeg_audio_lame['raw']['vbr_method']][$thisfile_mpeg_audio_lame['raw']['noise_shaping']][$thisfile_mpeg_audio_lame['raw']['stereo_mode']][$thisfile_mpeg_audio_lame['ath_type']][$thisfile_mpeg_audio_lame['lowpass_frequency']])) {
|
238 |
+
|
239 |
+
$encoder_options = $KnownEncoderValues[$thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate']][$thisfile_mpeg_audio_lame['vbr_quality']][$thisfile_mpeg_audio_lame['raw']['vbr_method']][$thisfile_mpeg_audio_lame['raw']['noise_shaping']][$thisfile_mpeg_audio_lame['raw']['stereo_mode']][$thisfile_mpeg_audio_lame['ath_type']][$thisfile_mpeg_audio_lame['lowpass_frequency']];
|
240 |
+
|
241 |
+
} elseif (isset($KnownEncoderValues['**'][$thisfile_mpeg_audio_lame['vbr_quality']][$thisfile_mpeg_audio_lame['raw']['vbr_method']][$thisfile_mpeg_audio_lame['raw']['noise_shaping']][$thisfile_mpeg_audio_lame['raw']['stereo_mode']][$thisfile_mpeg_audio_lame['ath_type']][$thisfile_mpeg_audio_lame['lowpass_frequency']])) {
|
242 |
+
|
243 |
+
$encoder_options = $KnownEncoderValues['**'][$thisfile_mpeg_audio_lame['vbr_quality']][$thisfile_mpeg_audio_lame['raw']['vbr_method']][$thisfile_mpeg_audio_lame['raw']['noise_shaping']][$thisfile_mpeg_audio_lame['raw']['stereo_mode']][$thisfile_mpeg_audio_lame['ath_type']][$thisfile_mpeg_audio_lame['lowpass_frequency']];
|
244 |
+
|
245 |
+
} elseif ($ThisFileInfo['audio']['bitrate_mode'] == 'vbr') {
|
246 |
+
|
247 |
+
// http://gabriel.mp3-tech.org/mp3infotag.html
|
248 |
+
// int Quality = (100 - 10 * gfp->VBR_q - gfp->quality)h
|
249 |
+
|
250 |
+
|
251 |
+
$LAME_V_value = 10 - ceil($thisfile_mpeg_audio_lame['vbr_quality'] / 10);
|
252 |
+
$LAME_q_value = 100 - $thisfile_mpeg_audio_lame['vbr_quality'] - ($LAME_V_value * 10);
|
253 |
+
$encoder_options = '-V'.$LAME_V_value.' -q'.$LAME_q_value;
|
254 |
+
|
255 |
+
} elseif ($ThisFileInfo['audio']['bitrate_mode'] == 'cbr') {
|
256 |
+
|
257 |
+
$encoder_options = strtoupper($ThisFileInfo['audio']['bitrate_mode']).ceil($ThisFileInfo['audio']['bitrate'] / 1000);
|
258 |
+
|
259 |
+
} else {
|
260 |
+
|
261 |
+
$encoder_options = strtoupper($ThisFileInfo['audio']['bitrate_mode']);
|
262 |
+
|
263 |
+
}
|
264 |
+
|
265 |
+
} elseif (!empty($thisfile_mpeg_audio_lame['bitrate_abr'])) {
|
266 |
+
|
267 |
+
$encoder_options = 'ABR'.$thisfile_mpeg_audio_lame['bitrate_abr'];
|
268 |
+
|
269 |
+
} elseif (!empty($ThisFileInfo['audio']['bitrate'])) {
|
270 |
+
|
271 |
+
if ($ThisFileInfo['audio']['bitrate_mode'] == 'cbr') {
|
272 |
+
$encoder_options = strtoupper($ThisFileInfo['audio']['bitrate_mode']).ceil($ThisFileInfo['audio']['bitrate'] / 1000);
|
273 |
+
} else {
|
274 |
+
$encoder_options = strtoupper($ThisFileInfo['audio']['bitrate_mode']);
|
275 |
+
}
|
276 |
+
|
277 |
+
}
|
278 |
+
if (!empty($thisfile_mpeg_audio_lame['bitrate_min'])) {
|
279 |
+
$encoder_options .= ' -b'.$thisfile_mpeg_audio_lame['bitrate_min'];
|
280 |
+
}
|
281 |
+
|
282 |
+
if (@$thisfile_mpeg_audio_lame['encoding_flags']['nogap_prev'] || @$thisfile_mpeg_audio_lame['encoding_flags']['nogap_next']) {
|
283 |
+
$encoder_options .= ' --nogap';
|
284 |
+
}
|
285 |
+
|
286 |
+
if (!empty($thisfile_mpeg_audio_lame['lowpass_frequency'])) {
|
287 |
+
$ExplodedOptions = explode(' ', $encoder_options, 4);
|
288 |
+
if ($ExplodedOptions[0] == '--r3mix') {
|
289 |
+
$ExplodedOptions[1] = 'r3mix';
|
290 |
+
}
|
291 |
+
switch ($ExplodedOptions[0]) {
|
292 |
+
case '--preset':
|
293 |
+
case '--alt-preset':
|
294 |
+
case '--r3mix':
|
295 |
+
if ($ExplodedOptions[1] == 'fast') {
|
296 |
+
$ExplodedOptions[1] .= ' '.$ExplodedOptions[2];
|
297 |
+
}
|
298 |
+
switch ($ExplodedOptions[1]) {
|
299 |
+
case 'portable':
|
300 |
+
case 'medium':
|
301 |
+
case 'standard':
|
302 |
+
case 'extreme':
|
303 |
+
case 'insane':
|
304 |
+
case 'fast portable':
|
305 |
+
case 'fast medium':
|
306 |
+
case 'fast standard':
|
307 |
+
case 'fast extreme':
|
308 |
+
case 'fast insane':
|
309 |
+
case 'r3mix':
|
310 |
+
static $ExpectedLowpass = array(
|
311 |
+
'insane|20500' => 20500,
|
312 |
+
'insane|20600' => 20600, // 3.90.2, 3.90.3, 3.91
|
313 |
+
'medium|18000' => 18000,
|
314 |
+
'fast medium|18000' => 18000,
|
315 |
+
'extreme|19500' => 19500, // 3.90, 3.90.1, 3.92, 3.95
|
316 |
+
'extreme|19600' => 19600, // 3.90.2, 3.90.3, 3.91, 3.93.1
|
317 |
+
'fast extreme|19500' => 19500, // 3.90, 3.90.1, 3.92, 3.95
|
318 |
+
'fast extreme|19600' => 19600, // 3.90.2, 3.90.3, 3.91, 3.93.1
|
319 |
+
'standard|19000' => 19000,
|
320 |
+
'fast standard|19000' => 19000,
|
321 |
+
'r3mix|19500' => 19500, // 3.90, 3.90.1, 3.92
|
322 |
+
'r3mix|19600' => 19600, // 3.90.2, 3.90.3, 3.91
|
323 |
+
'r3mix|18000' => 18000, // 3.94, 3.95
|
324 |
+
);
|
325 |
+
if (!isset($ExpectedLowpass[$ExplodedOptions[1].'|'.$thisfile_mpeg_audio_lame['lowpass_frequency']]) && ($thisfile_mpeg_audio_lame['lowpass_frequency'] < 22050) && (round($thisfile_mpeg_audio_lame['lowpass_frequency'] / 1000) < round($thisfile_mpeg_audio['sample_rate'] / 2000))) {
|
326 |
+
$encoder_options .= ' --lowpass '.$thisfile_mpeg_audio_lame['lowpass_frequency'];
|
327 |
+
}
|
328 |
+
break;
|
329 |
+
|
330 |
+
default:
|
331 |
+
break;
|
332 |
+
}
|
333 |
+
break;
|
334 |
+
}
|
335 |
+
}
|
336 |
+
|
337 |
+
if (isset($thisfile_mpeg_audio_lame['raw']['source_sample_freq'])) {
|
338 |
+
if (($thisfile_mpeg_audio['sample_rate'] == 44100) && ($thisfile_mpeg_audio_lame['raw']['source_sample_freq'] != 1)) {
|
339 |
+
$encoder_options .= ' --resample 44100';
|
340 |
+
} elseif (($thisfile_mpeg_audio['sample_rate'] == 48000) && ($thisfile_mpeg_audio_lame['raw']['source_sample_freq'] != 2)) {
|
341 |
+
$encoder_options .= ' --resample 48000';
|
342 |
+
} elseif ($thisfile_mpeg_audio['sample_rate'] < 44100) {
|
343 |
+
switch ($thisfile_mpeg_audio_lame['raw']['source_sample_freq']) {
|
344 |
+
case 0: // <= 32000
|
345 |
+
// may or may not be same as source frequency - ignore
|
346 |
+
break;
|
347 |
+
case 1: // 44100
|
348 |
+
case 2: // 48000
|
349 |
+
case 3: // 48000+
|
350 |
+
$ExplodedOptions = explode(' ', $encoder_options, 4);
|
351 |
+
switch ($ExplodedOptions[0]) {
|
352 |
+
case '--preset':
|
353 |
+
case '--alt-preset':
|
354 |
+
switch ($ExplodedOptions[1]) {
|
355 |
+
case 'fast':
|
356 |
+
case 'portable':
|
357 |
+
case 'medium':
|
358 |
+
case 'standard':
|
359 |
+
case 'extreme':
|
360 |
+
case 'insane':
|
361 |
+
$encoder_options .= ' --resample '.$thisfile_mpeg_audio['sample_rate'];
|
362 |
+
break;
|
363 |
+
|
364 |
+
default:
|
365 |
+
static $ExpectedResampledRate = array(
|
366 |
+
'phon+/lw/mw-eu/sw|16000' => 16000,
|
367 |
+
'mw-us|24000' => 24000, // 3.95
|
368 |
+
'mw-us|32000' => 32000, // 3.93
|
369 |
+
'mw-us|16000' => 16000, // 3.92
|
370 |
+
'phone|16000' => 16000,
|
371 |
+
'phone|11025' => 11025, // 3.94a15
|
372 |
+
'radio|32000' => 32000, // 3.94a15
|
373 |
+
'fm/radio|32000' => 32000, // 3.92
|
374 |
+
'fm|32000' => 32000, // 3.90
|
375 |
+
'voice|32000' => 32000);
|
376 |
+
if (!isset($ExpectedResampledRate[$ExplodedOptions[1].'|'.$thisfile_mpeg_audio['sample_rate']])) {
|
377 |
+
$encoder_options .= ' --resample '.$thisfile_mpeg_audio['sample_rate'];
|
378 |
+
}
|
379 |
+
break;
|
380 |
+
}
|
381 |
+
break;
|
382 |
+
|
383 |
+
case '--r3mix':
|
384 |
+
default:
|
385 |
+
$encoder_options .= ' --resample '.$thisfile_mpeg_audio['sample_rate'];
|
386 |
+
break;
|
387 |
+
}
|
388 |
+
break;
|
389 |
+
}
|
390 |
+
}
|
391 |
+
}
|
392 |
+
if (empty($encoder_options) && !empty($ThisFileInfo['audio']['bitrate']) && !empty($ThisFileInfo['audio']['bitrate_mode'])) {
|
393 |
+
//$encoder_options = strtoupper($ThisFileInfo['audio']['bitrate_mode']).ceil($ThisFileInfo['audio']['bitrate'] / 1000);
|
394 |
+
$encoder_options = strtoupper($ThisFileInfo['audio']['bitrate_mode']);
|
395 |
+
}
|
396 |
+
|
397 |
+
return $encoder_options;
|
398 |
+
}
|
399 |
+
|
400 |
+
|
401 |
+
function decodeMPEGaudioHeader($fd, $offset, &$ThisFileInfo, $recursivesearch=true, $ScanAsCBR=false, $FastMPEGheaderScan=false) {
|
402 |
+
|
403 |
+
static $MPEGaudioVersionLookup;
|
404 |
+
static $MPEGaudioLayerLookup;
|
405 |
+
static $MPEGaudioBitrateLookup;
|
406 |
+
static $MPEGaudioFrequencyLookup;
|
407 |
+
static $MPEGaudioChannelModeLookup;
|
408 |
+
static $MPEGaudioModeExtensionLookup;
|
409 |
+
static $MPEGaudioEmphasisLookup;
|
410 |
+
if (empty($MPEGaudioVersionLookup)) {
|
411 |
+
$MPEGaudioVersionLookup = getid3_mp3::MPEGaudioVersionArray();
|
412 |
+
$MPEGaudioLayerLookup = getid3_mp3::MPEGaudioLayerArray();
|
413 |
+
$MPEGaudioBitrateLookup = getid3_mp3::MPEGaudioBitrateArray();
|
414 |
+
$MPEGaudioFrequencyLookup = getid3_mp3::MPEGaudioFrequencyArray();
|
415 |
+
$MPEGaudioChannelModeLookup = getid3_mp3::MPEGaudioChannelModeArray();
|
416 |
+
$MPEGaudioModeExtensionLookup = getid3_mp3::MPEGaudioModeExtensionArray();
|
417 |
+
$MPEGaudioEmphasisLookup = getid3_mp3::MPEGaudioEmphasisArray();
|
418 |
+
}
|
419 |
+
|
420 |
+
if ($offset >= $ThisFileInfo['avdataend']) {
|
421 |
+
$ThisFileInfo['error'][] = 'end of file encounter looking for MPEG synch';
|
422 |
+
return false;
|
423 |
+
}
|
424 |
+
fseek($fd, $offset, SEEK_SET);
|
425 |
+
//$headerstring = fread($fd, 1441); // worst-case max length = 32kHz @ 320kbps layer 3 = 1441 bytes/frame
|
426 |
+
$headerstring = fread($fd, 226); // LAME header at offset 36 + 190 bytes of Xing/LAME data
|
427 |
+
|
428 |
+
// MP3 audio frame structure:
|
429 |
+
// $aa $aa $aa $aa [$bb $bb] $cc...
|
430 |
+
// where $aa..$aa is the four-byte mpeg-audio header (below)
|
431 |
+
// $bb $bb is the optional 2-byte CRC
|
432 |
+
// and $cc... is the audio data
|
433 |
+
|
434 |
+
$head4 = substr($headerstring, 0, 4);
|
435 |
+
|
436 |
+
static $MPEGaudioHeaderDecodeCache = array();
|
437 |
+
if (isset($MPEGaudioHeaderDecodeCache[$head4])) {
|
438 |
+
$MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$head4];
|
439 |
+
} else {
|
440 |
+
$MPEGheaderRawArray = getid3_mp3::MPEGaudioHeaderDecode($head4);
|
441 |
+
$MPEGaudioHeaderDecodeCache[$head4] = $MPEGheaderRawArray;
|
442 |
+
}
|
443 |
+
|
444 |
+
static $MPEGaudioHeaderValidCache = array();
|
445 |
+
|
446 |
+
// Not in cache
|
447 |
+
if (!isset($MPEGaudioHeaderValidCache[$head4])) {
|
448 |
+
//$MPEGaudioHeaderValidCache[$head4] = getid3_mp3::MPEGaudioHeaderValid($MPEGheaderRawArray, false, true); // allow badly-formatted freeformat (from LAME 3.90 - 3.93.1)
|
449 |
+
$MPEGaudioHeaderValidCache[$head4] = getid3_mp3::MPEGaudioHeaderValid($MPEGheaderRawArray, false, false);
|
450 |
+
}
|
451 |
+
|
452 |
+
// shortcut
|
453 |
+
if (!isset($ThisFileInfo['mpeg']['audio'])) {
|
454 |
+
$ThisFileInfo['mpeg']['audio'] = array();
|
455 |
+
}
|
456 |
+
$thisfile_mpeg_audio = &$ThisFileInfo['mpeg']['audio'];
|
457 |
+
|
458 |
+
|
459 |
+
if ($MPEGaudioHeaderValidCache[$head4]) {
|
460 |
+
$thisfile_mpeg_audio['raw'] = $MPEGheaderRawArray;
|
461 |
+
} else {
|
462 |
+
$ThisFileInfo['error'][] = 'Invalid MPEG audio header at offset '.$offset;
|
463 |
+
return false;
|
464 |
+
}
|
465 |
+
|
466 |
+
if (!$FastMPEGheaderScan) {
|
467 |
+
|
468 |
+
$thisfile_mpeg_audio['version'] = $MPEGaudioVersionLookup[$thisfile_mpeg_audio['raw']['version']];
|
469 |
+
$thisfile_mpeg_audio['layer'] = $MPEGaudioLayerLookup[$thisfile_mpeg_audio['raw']['layer']];
|
470 |
+
|
471 |
+
$thisfile_mpeg_audio['channelmode'] = $MPEGaudioChannelModeLookup[$thisfile_mpeg_audio['raw']['channelmode']];
|
472 |
+
$thisfile_mpeg_audio['channels'] = (($thisfile_mpeg_audio['channelmode'] == 'mono') ? 1 : 2);
|
473 |
+
$thisfile_mpeg_audio['sample_rate'] = $MPEGaudioFrequencyLookup[$thisfile_mpeg_audio['version']][$thisfile_mpeg_audio['raw']['sample_rate']];
|
474 |
+
$thisfile_mpeg_audio['protection'] = !$thisfile_mpeg_audio['raw']['protection'];
|
475 |
+
$thisfile_mpeg_audio['private'] = (bool) $thisfile_mpeg_audio['raw']['private'];
|
476 |
+
$thisfile_mpeg_audio['modeextension'] = $MPEGaudioModeExtensionLookup[$thisfile_mpeg_audio['layer']][$thisfile_mpeg_audio['raw']['modeextension']];
|
477 |
+
$thisfile_mpeg_audio['copyright'] = (bool) $thisfile_mpeg_audio['raw']['copyright'];
|
478 |
+
$thisfile_mpeg_audio['original'] = (bool) $thisfile_mpeg_audio['raw']['original'];
|
479 |
+
$thisfile_mpeg_audio['emphasis'] = $MPEGaudioEmphasisLookup[$thisfile_mpeg_audio['raw']['emphasis']];
|
480 |
+
|
481 |
+
$ThisFileInfo['audio']['channels'] = $thisfile_mpeg_audio['channels'];
|
482 |
+
$ThisFileInfo['audio']['sample_rate'] = $thisfile_mpeg_audio['sample_rate'];
|
483 |
+
|
484 |
+
if ($thisfile_mpeg_audio['protection']) {
|
485 |
+
$thisfile_mpeg_audio['crc'] = getid3_lib::BigEndian2Int(substr($headerstring, 4, 2));
|
486 |
+
}
|
487 |
+
|
488 |
+
}
|
489 |
+
|
490 |
+
if ($thisfile_mpeg_audio['raw']['bitrate'] == 15) {
|
491 |
+
// http://www.hydrogenaudio.org/?act=ST&f=16&t=9682&st=0
|
492 |
+
$ThisFileInfo['warning'][] = 'Invalid bitrate index (15), this is a known bug in free-format MP3s encoded by LAME v3.90 - 3.93.1';
|
493 |
+
$thisfile_mpeg_audio['raw']['bitrate'] = 0;
|
494 |
+
}
|
495 |
+
$thisfile_mpeg_audio['padding'] = (bool) $thisfile_mpeg_audio['raw']['padding'];
|
496 |
+
$thisfile_mpeg_audio['bitrate'] = $MPEGaudioBitrateLookup[$thisfile_mpeg_audio['version']][$thisfile_mpeg_audio['layer']][$thisfile_mpeg_audio['raw']['bitrate']];
|
497 |
+
|
498 |
+
if (($thisfile_mpeg_audio['bitrate'] == 'free') && ($offset == $ThisFileInfo['avdataoffset'])) {
|
499 |
+
// only skip multiple frame check if free-format bitstream found at beginning of file
|
500 |
+
// otherwise is quite possibly simply corrupted data
|
501 |
+
$recursivesearch = false;
|
502 |
+
}
|
503 |
+
|
504 |
+
// For Layer 2 there are some combinations of bitrate and mode which are not allowed.
|
505 |
+
if (!$FastMPEGheaderScan && ($thisfile_mpeg_audio['layer'] == '2')) {
|
506 |
+
|
507 |
+
$ThisFileInfo['audio']['dataformat'] = 'mp2';
|
508 |
+
switch ($thisfile_mpeg_audio['channelmode']) {
|
509 |
+
|
510 |
+
case 'mono':
|
511 |
+
if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] <= 192000)) {
|
512 |
+
// these are ok
|
513 |
+
} else {
|
514 |
+
$ThisFileInfo['error'][] = $thisfile_mpeg_audio['bitrate'].'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.';
|
515 |
+
return false;
|
516 |
+
}
|
517 |
+
break;
|
518 |
+
|
519 |
+
case 'stereo':
|
520 |
+
case 'joint stereo':
|
521 |
+
case 'dual channel':
|
522 |
+
if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] == 64000) || ($thisfile_mpeg_audio['bitrate'] >= 96000)) {
|
523 |
+
// these are ok
|
524 |
+
} else {
|
525 |
+
$ThisFileInfo['error'][] = intval(round($thisfile_mpeg_audio['bitrate'] / 1000)).'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.';
|
526 |
+
return false;
|
527 |
+
}
|
528 |
+
break;
|
529 |
+
|
530 |
+
}
|
531 |
+
|
532 |
+
}
|
533 |
+
|
534 |
+
|
535 |
+
if ($ThisFileInfo['audio']['sample_rate'] > 0) {
|
536 |
+
$thisfile_mpeg_audio['framelength'] = getid3_mp3::MPEGaudioFrameLength($thisfile_mpeg_audio['bitrate'], $thisfile_mpeg_audio['version'], $thisfile_mpeg_audio['layer'], (int) $thisfile_mpeg_audio['padding'], $ThisFileInfo['audio']['sample_rate']);
|
537 |
+
}
|
538 |
+
|
539 |
+
$nextframetestoffset = $offset + 1;
|
540 |
+
if ($thisfile_mpeg_audio['bitrate'] != 'free') {
|
541 |
+
|
542 |
+
$ThisFileInfo['audio']['bitrate'] = $thisfile_mpeg_audio['bitrate'];
|
543 |
+
|
544 |
+
if (isset($thisfile_mpeg_audio['framelength'])) {
|
545 |
+
$nextframetestoffset = $offset + $thisfile_mpeg_audio['framelength'];
|
546 |
+
} else {
|
547 |
+
$ThisFileInfo['error'][] = 'Frame at offset('.$offset.') is has an invalid frame length.';
|
548 |
+
return false;
|
549 |
+
}
|
550 |
+
|
551 |
+
}
|
552 |
+
|
553 |
+
$ExpectedNumberOfAudioBytes = 0;
|
554 |
+
|
555 |
+
////////////////////////////////////////////////////////////////////////////////////
|
556 |
+
// Variable-bitrate headers
|
557 |
+
|
558 |
+
if (substr($headerstring, 4 + 32, 4) == 'VBRI') {
|
559 |
+
// Fraunhofer VBR header is hardcoded 'VBRI' at offset 0x24 (36)
|
560 |
+
// specs taken from http://minnie.tuhs.org/pipermail/mp3encoder/2001-January/001800.html
|
561 |
+
|
562 |
+
$thisfile_mpeg_audio['bitrate_mode'] = 'vbr';
|
563 |
+
$thisfile_mpeg_audio['VBR_method'] = 'Fraunhofer';
|
564 |
+
$ThisFileInfo['audio']['codec'] = 'Fraunhofer';
|
565 |
+
|
566 |
+
$SideInfoData = substr($headerstring, 4 + 2, 32);
|
567 |
+
|
568 |
+
$FraunhoferVBROffset = 36;
|
569 |
+
|
570 |
+
$thisfile_mpeg_audio['VBR_encoder_version'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 4, 2)); // VbriVersion
|
571 |
+
$thisfile_mpeg_audio['VBR_encoder_delay'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 6, 2)); // VbriDelay
|
572 |
+
$thisfile_mpeg_audio['VBR_quality'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 8, 2)); // VbriQuality
|
573 |
+
$thisfile_mpeg_audio['VBR_bytes'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 10, 4)); // VbriStreamBytes
|
574 |
+
$thisfile_mpeg_audio['VBR_frames'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 14, 4)); // VbriStreamFrames
|
575 |
+
$thisfile_mpeg_audio['VBR_seek_offsets'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 18, 2)); // VbriTableSize
|
576 |
+
$thisfile_mpeg_audio['VBR_seek_scale'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 20, 2)); // VbriTableScale
|
577 |
+
$thisfile_mpeg_audio['VBR_entry_bytes'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 22, 2)); // VbriEntryBytes
|
578 |
+
$thisfile_mpeg_audio['VBR_entry_frames'] = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 24, 2)); // VbriEntryFrames
|
579 |
+
|
580 |
+
$ExpectedNumberOfAudioBytes = $thisfile_mpeg_audio['VBR_bytes'];
|
581 |
+
|
582 |
+
$previousbyteoffset = $offset;
|
583 |
+
for ($i = 0; $i < $thisfile_mpeg_audio['VBR_seek_offsets']; $i++) {
|
584 |
+
$Fraunhofer_OffsetN = getid3_lib::BigEndian2Int(substr($headerstring, $FraunhoferVBROffset, $thisfile_mpeg_audio['VBR_entry_bytes']));
|
585 |
+
$FraunhoferVBROffset += $thisfile_mpeg_audio['VBR_entry_bytes'];
|
586 |
+
$thisfile_mpeg_audio['VBR_offsets_relative'][$i] = ($Fraunhofer_OffsetN * $thisfile_mpeg_audio['VBR_seek_scale']);
|
587 |
+
$thisfile_mpeg_audio['VBR_offsets_absolute'][$i] = ($Fraunhofer_OffsetN * $thisfile_mpeg_audio['VBR_seek_scale']) + $previousbyteoffset;
|
588 |
+
$previousbyteoffset += $Fraunhofer_OffsetN;
|
589 |
+
}
|
590 |
+
|
591 |
+
|
592 |
+
} else {
|
593 |
+
|
594 |
+
// Xing VBR header is hardcoded 'Xing' at a offset 0x0D (13), 0x15 (21) or 0x24 (36)
|
595 |
+
// depending on MPEG layer and number of channels
|
596 |
+
|
597 |
+
$VBRidOffset = getid3_mp3::XingVBRidOffset($thisfile_mpeg_audio['version'], $thisfile_mpeg_audio['channelmode']);
|
598 |
+
$SideInfoData = substr($headerstring, 4 + 2, $VBRidOffset - 4);
|
599 |
+
|
600 |
+
if ((substr($headerstring, $VBRidOffset, strlen('Xing')) == 'Xing') || (substr($headerstring, $VBRidOffset, strlen('Info')) == 'Info')) {
|
601 |
+
// 'Xing' is traditional Xing VBR frame
|
602 |
+
// 'Info' is LAME-encoded CBR (This was done to avoid CBR files to be recognized as traditional Xing VBR files by some decoders.)
|
603 |
+
// 'Info' *can* legally be used to specify a VBR file as well, however.
|
604 |
+
|
605 |
+
// http://www.multiweb.cz/twoinches/MP3inside.htm
|
606 |
+
//00..03 = "Xing" or "Info"
|
607 |
+
//04..07 = Flags:
|
608 |
+
// 0x01 Frames Flag set if value for number of frames in file is stored
|
609 |
+
// 0x02 Bytes Flag set if value for filesize in bytes is stored
|
610 |
+
// 0x04 TOC Flag set if values for TOC are stored
|
611 |
+
// 0x08 VBR Scale Flag set if values for VBR scale is stored
|
612 |
+
//08..11 Frames: Number of frames in file (including the first Xing/Info one)
|
613 |
+
//12..15 Bytes: File length in Bytes
|
614 |
+
//16..115 TOC (Table of Contents):
|
615 |
+
// Contains of 100 indexes (one Byte length) for easier lookup in file. Approximately solves problem with moving inside file.
|
616 |
+
// Each Byte has a value according this formula:
|
617 |
+
// (TOC[i] / 256) * fileLenInBytes
|
618 |
+
// So if song lasts eg. 240 sec. and you want to jump to 60. sec. (and file is 5 000 000 Bytes length) you can use:
|
619 |
+
// TOC[(60/240)*100] = TOC[25]
|
620 |
+
// and corresponding Byte in file is then approximately at:
|
621 |
+
// (TOC[25]/256) * 5000000
|
622 |
+
//116..119 VBR Scale
|
623 |
+
|
624 |
+
|
625 |
+
// should be safe to leave this at 'vbr' and let it be overriden to 'cbr' if a CBR preset/mode is used by LAME
|
626 |
+
// if (substr($headerstring, $VBRidOffset, strlen('Info')) == 'Xing') {
|
627 |
+
$thisfile_mpeg_audio['bitrate_mode'] = 'vbr';
|
628 |
+
$thisfile_mpeg_audio['VBR_method'] = 'Xing';
|
629 |
+
// } else {
|
630 |
+
// $ScanAsCBR = true;
|
631 |
+
// $thisfile_mpeg_audio['bitrate_mode'] = 'cbr';
|
632 |
+
// }
|
633 |
+
|
634 |
+
$thisfile_mpeg_audio['xing_flags_raw'] = getid3_lib::BigEndian2Int(substr($headerstring, $VBRidOffset + 4, 4));
|
635 |
+
|
636 |
+
$thisfile_mpeg_audio['xing_flags']['frames'] = (bool) ($thisfile_mpeg_audio['xing_flags_raw'] & 0x00000001);
|
637 |
+
$thisfile_mpeg_audio['xing_flags']['bytes'] = (bool) ($thisfile_mpeg_audio['xing_flags_raw'] & 0x00000002);
|
638 |
+
$thisfile_mpeg_audio['xing_flags']['toc'] = (bool) ($thisfile_mpeg_audio['xing_flags_raw'] & 0x00000004);
|
639 |
+
$thisfile_mpeg_audio['xing_flags']['vbr_scale'] = (bool) ($thisfile_mpeg_audio['xing_flags_raw'] & 0x00000008);
|
640 |
+
|
641 |
+
if ($thisfile_mpeg_audio['xing_flags']['frames']) {
|
642 |
+
$thisfile_mpeg_audio['VBR_frames'] = getid3_lib::BigEndian2Int(substr($headerstring, $VBRidOffset + 8, 4));
|
643 |
+
//$thisfile_mpeg_audio['VBR_frames']--; // don't count header Xing/Info frame
|
644 |
+
}
|
645 |
+
if ($thisfile_mpeg_audio['xing_flags']['bytes']) {
|
646 |
+
$thisfile_mpeg_audio['VBR_bytes'] = getid3_lib::BigEndian2Int(substr($headerstring, $VBRidOffset + 12, 4));
|
647 |
+
}
|
648 |
+
|
649 |
+
//if (($thisfile_mpeg_audio['bitrate'] == 'free') && !empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
|
650 |
+
if (!empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
|
651 |
+
|
652 |
+
$framelengthfloat = $thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames'];
|
653 |
+
|
654 |
+
if ($thisfile_mpeg_audio['layer'] == '1') {
|
655 |
+
// BitRate = (((FrameLengthInBytes / 4) - Padding) * SampleRate) / 12
|
656 |
+
//$ThisFileInfo['audio']['bitrate'] = ((($framelengthfloat / 4) - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 12;
|
657 |
+
$ThisFileInfo['audio']['bitrate'] = ($framelengthfloat / 4) * $thisfile_mpeg_audio['sample_rate'] * (2 / $ThisFileInfo['audio']['channels']) / 12;
|
658 |
+
} else {
|
659 |
+
// Bitrate = ((FrameLengthInBytes - Padding) * SampleRate) / 144
|
660 |
+
//$ThisFileInfo['audio']['bitrate'] = (($framelengthfloat - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 144;
|
661 |
+
$ThisFileInfo['audio']['bitrate'] = $framelengthfloat * $thisfile_mpeg_audio['sample_rate'] * (2 / $ThisFileInfo['audio']['channels']) / 144;
|
662 |
+
}
|
663 |
+
$thisfile_mpeg_audio['framelength'] = floor($framelengthfloat);
|
664 |
+
}
|
665 |
+
|
666 |
+
if ($thisfile_mpeg_audio['xing_flags']['toc']) {
|
667 |
+
$LAMEtocData = substr($headerstring, $VBRidOffset + 16, 100);
|
668 |
+
for ($i = 0; $i < 100; $i++) {
|
669 |
+
$thisfile_mpeg_audio['toc'][$i] = ord($LAMEtocData{$i});
|
670 |
+
}
|
671 |
+
}
|
672 |
+
if ($thisfile_mpeg_audio['xing_flags']['vbr_scale']) {
|
673 |
+
$thisfile_mpeg_audio['VBR_scale'] = getid3_lib::BigEndian2Int(substr($headerstring, $VBRidOffset + 116, 4));
|
674 |
+
}
|
675 |
+
|
676 |
+
|
677 |
+
// http://gabriel.mp3-tech.org/mp3infotag.html
|
678 |
+
if (substr($headerstring, $VBRidOffset + 120, 4) == 'LAME') {
|
679 |
+
|
680 |
+
// shortcut
|
681 |
+
$thisfile_mpeg_audio['LAME'] = array();
|
682 |
+
$thisfile_mpeg_audio_lame = &$thisfile_mpeg_audio['LAME'];
|
683 |
+
|
684 |
+
|
685 |
+
$thisfile_mpeg_audio_lame['long_version'] = substr($headerstring, $VBRidOffset + 120, 20);
|
686 |
+
$thisfile_mpeg_audio_lame['short_version'] = substr($thisfile_mpeg_audio_lame['long_version'], 0, 9);
|
687 |
+
|
688 |
+
if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.90') {
|
689 |
+
|
690 |
+
// extra 11 chars are not part of version string when LAMEtag present
|
691 |
+
unset($thisfile_mpeg_audio_lame['long_version']);
|
692 |
+
|
693 |
+
// It the LAME tag was only introduced in LAME v3.90
|
694 |
+
// http://www.hydrogenaudio.org/?act=ST&f=15&t=9933
|
695 |
+
|
696 |
+
// Offsets of various bytes in http://gabriel.mp3-tech.org/mp3infotag.html
|
697 |
+
// are assuming a 'Xing' identifier offset of 0x24, which is the case for
|
698 |
+
// MPEG-1 non-mono, but not for other combinations
|
699 |
+
$LAMEtagOffsetContant = $VBRidOffset - 0x24;
|
700 |
+
|
701 |
+
// shortcuts
|
702 |
+
$thisfile_mpeg_audio_lame['RGAD'] = array('track'=>array(), 'album'=>array());
|
703 |
+
$thisfile_mpeg_audio_lame_RGAD = &$thisfile_mpeg_audio_lame['RGAD'];
|
704 |
+
$thisfile_mpeg_audio_lame_RGAD_track = &$thisfile_mpeg_audio_lame_RGAD['track'];
|
705 |
+
$thisfile_mpeg_audio_lame_RGAD_album = &$thisfile_mpeg_audio_lame_RGAD['album'];
|
706 |
+
$thisfile_mpeg_audio_lame['raw'] = array();
|
707 |
+
$thisfile_mpeg_audio_lame_raw = &$thisfile_mpeg_audio_lame['raw'];
|
708 |
+
|
709 |
+
// byte $9B VBR Quality
|
710 |
+
// This field is there to indicate a quality level, although the scale was not precised in the original Xing specifications.
|
711 |
+
// Actually overwrites original Xing bytes
|
712 |
+
unset($thisfile_mpeg_audio['VBR_scale']);
|
713 |
+
$thisfile_mpeg_audio_lame['vbr_quality'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0x9B, 1));
|
714 |
+
|
715 |
+
// bytes $9C-$A4 Encoder short VersionString
|
716 |
+
$thisfile_mpeg_audio_lame['short_version'] = substr($headerstring, $LAMEtagOffsetContant + 0x9C, 9);
|
717 |
+
|
718 |
+
// byte $A5 Info Tag revision + VBR method
|
719 |
+
$LAMEtagRevisionVBRmethod = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA5, 1));
|
720 |
+
|
721 |
+
$thisfile_mpeg_audio_lame['tag_revision'] = ($LAMEtagRevisionVBRmethod & 0xF0) >> 4;
|
722 |
+
$thisfile_mpeg_audio_lame_raw['vbr_method'] = $LAMEtagRevisionVBRmethod & 0x0F;
|
723 |
+
$thisfile_mpeg_audio_lame['vbr_method'] = getid3_mp3::LAMEvbrMethodLookup($thisfile_mpeg_audio_lame_raw['vbr_method']);
|
724 |
+
$thisfile_mpeg_audio['bitrate_mode'] = substr($thisfile_mpeg_audio_lame['vbr_method'], 0, 3); // usually either 'cbr' or 'vbr', but truncates 'vbr-old / vbr-rh' to 'vbr'
|
725 |
+
|
726 |
+
// byte $A6 Lowpass filter value
|
727 |
+
$thisfile_mpeg_audio_lame['lowpass_frequency'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA6, 1)) * 100;
|
728 |
+
|
729 |
+
// bytes $A7-$AE Replay Gain
|
730 |
+
// http://privatewww.essex.ac.uk/~djmrob/replaygain/rg_data_format.html
|
731 |
+
// bytes $A7-$AA : 32 bit floating point "Peak signal amplitude"
|
732 |
+
if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.94b') {
|
733 |
+
// LAME 3.94a16 and later - 9.23 fixed point
|
734 |
+
// ie 0x0059E2EE / (2^23) = 5890798 / 8388608 = 0.7022378444671630859375
|
735 |
+
$thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] = (float) ((getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA7, 4))) / 8388608);
|
736 |
+
} else {
|
737 |
+
// LAME 3.94a15 and earlier - 32-bit floating point
|
738 |
+
// Actually 3.94a16 will fall in here too and be WRONG, but is hard to detect 3.94a16 vs 3.94a15
|
739 |
+
$thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] = getid3_lib::LittleEndian2Float(substr($headerstring, $LAMEtagOffsetContant + 0xA7, 4));
|
740 |
+
}
|
741 |
+
if ($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] == 0) {
|
742 |
+
unset($thisfile_mpeg_audio_lame_RGAD['peak_amplitude']);
|
743 |
+
} else {
|
744 |
+
$thisfile_mpeg_audio_lame_RGAD['peak_db'] = getid3_lib::RGADamplitude2dB($thisfile_mpeg_audio_lame_RGAD['peak_amplitude']);
|
745 |
+
}
|
746 |
+
|
747 |
+
$thisfile_mpeg_audio_lame_raw['RGAD_track'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAB, 2));
|
748 |
+
$thisfile_mpeg_audio_lame_raw['RGAD_album'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAD, 2));
|
749 |
+
|
750 |
+
|
751 |
+
if ($thisfile_mpeg_audio_lame_raw['RGAD_track'] != 0) {
|
752 |
+
|
753 |
+
$thisfile_mpeg_audio_lame_RGAD_track['raw']['name'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0xE000) >> 13;
|
754 |
+
$thisfile_mpeg_audio_lame_RGAD_track['raw']['originator'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x1C00) >> 10;
|
755 |
+
$thisfile_mpeg_audio_lame_RGAD_track['raw']['sign_bit'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x0200) >> 9;
|
756 |
+
$thisfile_mpeg_audio_lame_RGAD_track['raw']['gain_adjust'] = $thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x01FF;
|
757 |
+
$thisfile_mpeg_audio_lame_RGAD_track['name'] = getid3_lib::RGADnameLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['name']);
|
758 |
+
$thisfile_mpeg_audio_lame_RGAD_track['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['originator']);
|
759 |
+
$thisfile_mpeg_audio_lame_RGAD_track['gain_db'] = getid3_lib::RGADadjustmentLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['gain_adjust'], $thisfile_mpeg_audio_lame_RGAD_track['raw']['sign_bit']);
|
760 |
+
|
761 |
+
if (!empty($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'])) {
|
762 |
+
$ThisFileInfo['replay_gain']['track']['peak'] = $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'];
|
763 |
+
}
|
764 |
+
$ThisFileInfo['replay_gain']['track']['originator'] = $thisfile_mpeg_audio_lame_RGAD_track['originator'];
|
765 |
+
$ThisFileInfo['replay_gain']['track']['adjustment'] = $thisfile_mpeg_audio_lame_RGAD_track['gain_db'];
|
766 |
+
} else {
|
767 |
+
unset($thisfile_mpeg_audio_lame_RGAD['track']);
|
768 |
+
}
|
769 |
+
if ($thisfile_mpeg_audio_lame_raw['RGAD_album'] != 0) {
|
770 |
+
|
771 |
+
$thisfile_mpeg_audio_lame_RGAD_album['raw']['name'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0xE000) >> 13;
|
772 |
+
$thisfile_mpeg_audio_lame_RGAD_album['raw']['originator'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x1C00) >> 10;
|
773 |
+
$thisfile_mpeg_audio_lame_RGAD_album['raw']['sign_bit'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x0200) >> 9;
|
774 |
+
$thisfile_mpeg_audio_lame_RGAD_album['raw']['gain_adjust'] = $thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x01FF;
|
775 |
+
$thisfile_mpeg_audio_lame_RGAD_album['name'] = getid3_lib::RGADnameLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['name']);
|
776 |
+
$thisfile_mpeg_audio_lame_RGAD_album['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['originator']);
|
777 |
+
$thisfile_mpeg_audio_lame_RGAD_album['gain_db'] = getid3_lib::RGADadjustmentLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['gain_adjust'], $thisfile_mpeg_audio_lame_RGAD_album['raw']['sign_bit']);
|
778 |
+
|
779 |
+
if (!empty($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'])) {
|
780 |
+
$ThisFileInfo['replay_gain']['album']['peak'] = $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'];
|
781 |
+
}
|
782 |
+
$ThisFileInfo['replay_gain']['album']['originator'] = $thisfile_mpeg_audio_lame_RGAD_album['originator'];
|
783 |
+
$ThisFileInfo['replay_gain']['album']['adjustment'] = $thisfile_mpeg_audio_lame_RGAD_album['gain_db'];
|
784 |
+
} else {
|
785 |
+
unset($thisfile_mpeg_audio_lame_RGAD['album']);
|
786 |
+
}
|
787 |
+
if (empty($thisfile_mpeg_audio_lame_RGAD)) {
|
788 |
+
unset($thisfile_mpeg_audio_lame['RGAD']);
|
789 |
+
}
|
790 |
+
|
791 |
+
|
792 |
+
// byte $AF Encoding flags + ATH Type
|
793 |
+
$EncodingFlagsATHtype = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAF, 1));
|
794 |
+
$thisfile_mpeg_audio_lame['encoding_flags']['nspsytune'] = (bool) ($EncodingFlagsATHtype & 0x10);
|
795 |
+
$thisfile_mpeg_audio_lame['encoding_flags']['nssafejoint'] = (bool) ($EncodingFlagsATHtype & 0x20);
|
796 |
+
$thisfile_mpeg_audio_lame['encoding_flags']['nogap_next'] = (bool) ($EncodingFlagsATHtype & 0x40);
|
797 |
+
$thisfile_mpeg_audio_lame['encoding_flags']['nogap_prev'] = (bool) ($EncodingFlagsATHtype & 0x80);
|
798 |
+
$thisfile_mpeg_audio_lame['ath_type'] = $EncodingFlagsATHtype & 0x0F;
|
799 |
+
|
800 |
+
// byte $B0 if ABR {specified bitrate} else {minimal bitrate}
|
801 |
+
$thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB0, 1));
|
802 |
+
if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 2) { // Average BitRate (ABR)
|
803 |
+
$thisfile_mpeg_audio_lame['bitrate_abr'] = $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'];
|
804 |
+
} elseif ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) { // Constant BitRate (CBR)
|
805 |
+
// ignore
|
806 |
+
} elseif ($thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'] > 0) { // Variable BitRate (VBR) - minimum bitrate
|
807 |
+
$thisfile_mpeg_audio_lame['bitrate_min'] = $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'];
|
808 |
+
}
|
809 |
+
|
810 |
+
// bytes $B1-$B3 Encoder delays
|
811 |
+
$EncoderDelays = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB1, 3));
|
812 |
+
$thisfile_mpeg_audio_lame['encoder_delay'] = ($EncoderDelays & 0xFFF000) >> 12;
|
813 |
+
$thisfile_mpeg_audio_lame['end_padding'] = $EncoderDelays & 0x000FFF;
|
814 |
+
|
815 |
+
// byte $B4 Misc
|
816 |
+
$MiscByte = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB4, 1));
|
817 |
+
$thisfile_mpeg_audio_lame_raw['noise_shaping'] = ($MiscByte & 0x03);
|
818 |
+
$thisfile_mpeg_audio_lame_raw['stereo_mode'] = ($MiscByte & 0x1C) >> 2;
|
819 |
+
$thisfile_mpeg_audio_lame_raw['not_optimal_quality'] = ($MiscByte & 0x20) >> 5;
|
820 |
+
$thisfile_mpeg_audio_lame_raw['source_sample_freq'] = ($MiscByte & 0xC0) >> 6;
|
821 |
+
$thisfile_mpeg_audio_lame['noise_shaping'] = $thisfile_mpeg_audio_lame_raw['noise_shaping'];
|
822 |
+
$thisfile_mpeg_audio_lame['stereo_mode'] = getid3_mp3::LAMEmiscStereoModeLookup($thisfile_mpeg_audio_lame_raw['stereo_mode']);
|
823 |
+
$thisfile_mpeg_audio_lame['not_optimal_quality'] = (bool) $thisfile_mpeg_audio_lame_raw['not_optimal_quality'];
|
824 |
+
$thisfile_mpeg_audio_lame['source_sample_freq'] = getid3_mp3::LAMEmiscSourceSampleFrequencyLookup($thisfile_mpeg_audio_lame_raw['source_sample_freq']);
|
825 |
+
|
826 |
+
// byte $B5 MP3 Gain
|
827 |
+
$thisfile_mpeg_audio_lame_raw['mp3_gain'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB5, 1), false, true);
|
828 |
+
$thisfile_mpeg_audio_lame['mp3_gain_db'] = (getid3_lib::RGADamplitude2dB(2) / 4) * $thisfile_mpeg_audio_lame_raw['mp3_gain'];
|
829 |
+
$thisfile_mpeg_audio_lame['mp3_gain_factor'] = pow(2, ($thisfile_mpeg_audio_lame['mp3_gain_db'] / 6));
|
830 |
+
|
831 |
+
// bytes $B6-$B7 Preset and surround info
|
832 |
+
$PresetSurroundBytes = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB6, 2));
|
833 |
+
// Reserved = ($PresetSurroundBytes & 0xC000);
|
834 |
+
$thisfile_mpeg_audio_lame_raw['surround_info'] = ($PresetSurroundBytes & 0x3800);
|
835 |
+
$thisfile_mpeg_audio_lame['surround_info'] = getid3_mp3::LAMEsurroundInfoLookup($thisfile_mpeg_audio_lame_raw['surround_info']);
|
836 |
+
$thisfile_mpeg_audio_lame['preset_used_id'] = ($PresetSurroundBytes & 0x07FF);
|
837 |
+
$thisfile_mpeg_audio_lame['preset_used'] = getid3_mp3::LAMEpresetUsedLookup($thisfile_mpeg_audio_lame);
|
838 |
+
if (!empty($thisfile_mpeg_audio_lame['preset_used_id']) && empty($thisfile_mpeg_audio_lame['preset_used'])) {
|
839 |
+
$ThisFileInfo['warning'][] = 'Unknown LAME preset used ('.$thisfile_mpeg_audio_lame['preset_used_id'].') - please report to info@getid3.org';
|
840 |
+
}
|
841 |
+
if (($thisfile_mpeg_audio_lame['short_version'] == 'LAME3.90.') && !empty($thisfile_mpeg_audio_lame['preset_used_id'])) {
|
842 |
+
// this may change if 3.90.4 ever comes out
|
843 |
+
$thisfile_mpeg_audio_lame['short_version'] = 'LAME3.90.3';
|
844 |
+
}
|
845 |
+
|
846 |
+
// bytes $B8-$BB MusicLength
|
847 |
+
$thisfile_mpeg_audio_lame['audio_bytes'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB8, 4));
|
848 |
+
$ExpectedNumberOfAudioBytes = (($thisfile_mpeg_audio_lame['audio_bytes'] > 0) ? $thisfile_mpeg_audio_lame['audio_bytes'] : $thisfile_mpeg_audio['VBR_bytes']);
|
849 |
+
|
850 |
+
// bytes $BC-$BD MusicCRC
|
851 |
+
$thisfile_mpeg_audio_lame['music_crc'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBC, 2));
|
852 |
+
|
853 |
+
// bytes $BE-$BF CRC-16 of Info Tag
|
854 |
+
$thisfile_mpeg_audio_lame['lame_tag_crc'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBE, 2));
|
855 |
+
|
856 |
+
|
857 |
+
// LAME CBR
|
858 |
+
if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) {
|
859 |
+
|
860 |
+
$thisfile_mpeg_audio['bitrate_mode'] = 'cbr';
|
861 |
+
$thisfile_mpeg_audio['bitrate'] = getid3_mp3::ClosestStandardMP3Bitrate($thisfile_mpeg_audio['bitrate']);
|
862 |
+
$ThisFileInfo['audio']['bitrate'] = $thisfile_mpeg_audio['bitrate'];
|
863 |
+
//if (empty($thisfile_mpeg_audio['bitrate']) || (!empty($thisfile_mpeg_audio_lame['bitrate_min']) && ($thisfile_mpeg_audio_lame['bitrate_min'] != 255))) {
|
864 |
+
// $thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio_lame['bitrate_min'];
|
865 |
+
//}
|
866 |
+
|
867 |
+
}
|
868 |
+
|
869 |
+
}
|
870 |
+
}
|
871 |
+
|
872 |
+
} else {
|
873 |
+
|
874 |
+
// not Fraunhofer or Xing VBR methods, most likely CBR (but could be VBR with no header)
|
875 |
+
$thisfile_mpeg_audio['bitrate_mode'] = 'cbr';
|
876 |
+
if ($recursivesearch) {
|
877 |
+
$thisfile_mpeg_audio['bitrate_mode'] = 'vbr';
|
878 |
+
if (getid3_mp3::RecursiveFrameScanning($fd, $ThisFileInfo, $offset, $nextframetestoffset, true)) {
|
879 |
+
$recursivesearch = false;
|
880 |
+
$thisfile_mpeg_audio['bitrate_mode'] = 'cbr';
|
881 |
+
}
|
882 |
+
if ($thisfile_mpeg_audio['bitrate_mode'] == 'vbr') {
|
883 |
+
$ThisFileInfo['warning'][] = 'VBR file with no VBR header. Bitrate values calculated from actual frame bitrates.';
|
884 |
+
}
|
885 |
+
}
|
886 |
+
|
887 |
+
}
|
888 |
+
|
889 |
+
}
|
890 |
+
|
891 |
+
if (($ExpectedNumberOfAudioBytes > 0) && ($ExpectedNumberOfAudioBytes != ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']))) {
|
892 |
+
if ($ExpectedNumberOfAudioBytes > ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset'])) {
|
893 |
+
if (($ExpectedNumberOfAudioBytes - ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset'])) == 1) {
|
894 |
+
$ThisFileInfo['warning'][] = 'Last byte of data truncated (this is a known bug in Meracl ID3 Tag Writer before v1.3.5)';
|
895 |
+
} else {
|
896 |
+
$ThisFileInfo['warning'][] = 'Probable truncated file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, only found '.($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']).' (short by '.($ExpectedNumberOfAudioBytes - ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset'])).' bytes)';
|
897 |
+
}
|
898 |
+
} else {
|
899 |
+
if ((($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) - $ExpectedNumberOfAudioBytes) == 1) {
|
900 |
+
// $prenullbytefileoffset = ftell($fd);
|
901 |
+
// fseek($fd, $ThisFileInfo['avdataend'], SEEK_SET);
|
902 |
+
// $PossibleNullByte = fread($fd, 1);
|
903 |
+
// fseek($fd, $prenullbytefileoffset, SEEK_SET);
|
904 |
+
// if ($PossibleNullByte === "\x00") {
|
905 |
+
$ThisFileInfo['avdataend']--;
|
906 |
+
// $ThisFileInfo['warning'][] = 'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored';
|
907 |
+
// } else {
|
908 |
+
// $ThisFileInfo['warning'][] = 'Too much data in file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, found '.($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']).' ('.(($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) - $ExpectedNumberOfAudioBytes).' bytes too many)';
|
909 |
+
// }
|
910 |
+
} else {
|
911 |
+
$ThisFileInfo['warning'][] = 'Too much data in file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, found '.($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']).' ('.(($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) - $ExpectedNumberOfAudioBytes).' bytes too many)';
|
912 |
+
}
|
913 |
+
}
|
914 |
+
}
|
915 |
+
|
916 |
+
if (($thisfile_mpeg_audio['bitrate'] == 'free') && empty($ThisFileInfo['audio']['bitrate'])) {
|
917 |
+
if (($offset == $ThisFileInfo['avdataoffset']) && empty($thisfile_mpeg_audio['VBR_frames'])) {
|
918 |
+
$framebytelength = getid3_mp3::FreeFormatFrameLength($fd, $offset, $ThisFileInfo, true);
|
919 |
+
if ($framebytelength > 0) {
|
920 |
+
$thisfile_mpeg_audio['framelength'] = $framebytelength;
|
921 |
+
if ($thisfile_mpeg_audio['layer'] == '1') {
|
922 |
+
// BitRate = (((FrameLengthInBytes / 4) - Padding) * SampleRate) / 12
|
923 |
+
$ThisFileInfo['audio']['bitrate'] = ((($framebytelength / 4) - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 12;
|
924 |
+
} else {
|
925 |
+
// Bitrate = ((FrameLengthInBytes - Padding) * SampleRate) / 144
|
926 |
+
$ThisFileInfo['audio']['bitrate'] = (($framebytelength - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 144;
|
927 |
+
}
|
928 |
+
} else {
|
929 |
+
$ThisFileInfo['error'][] = 'Error calculating frame length of free-format MP3 without Xing/LAME header';
|
930 |
+
}
|
931 |
+
}
|
932 |
+
}
|
933 |
+
|
934 |
+
if (@$thisfile_mpeg_audio['VBR_frames']) {
|
935 |
+
switch ($thisfile_mpeg_audio['bitrate_mode']) {
|
936 |
+
case 'vbr':
|
937 |
+
case 'abr':
|
938 |
+
if (($thisfile_mpeg_audio['version'] == '1') && ($thisfile_mpeg_audio['layer'] == 1)) {
|
939 |
+
$thisfile_mpeg_audio['VBR_bitrate'] = ((@$thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames']) * 8) * ($ThisFileInfo['audio']['sample_rate'] / 384);
|
940 |
+
} elseif ((($thisfile_mpeg_audio['version'] == '2') || ($thisfile_mpeg_audio['version'] == '2.5')) && ($thisfile_mpeg_audio['layer'] == 3)) {
|
941 |
+
$thisfile_mpeg_audio['VBR_bitrate'] = ((@$thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames']) * 8) * ($ThisFileInfo['audio']['sample_rate'] / 576);
|
942 |
+
} else {
|
943 |
+
$thisfile_mpeg_audio['VBR_bitrate'] = ((@$thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames']) * 8) * ($ThisFileInfo['audio']['sample_rate'] / 1152);
|
944 |
+
}
|
945 |
+
if ($thisfile_mpeg_audio['VBR_bitrate'] > 0) {
|
946 |
+
$ThisFileInfo['audio']['bitrate'] = $thisfile_mpeg_audio['VBR_bitrate'];
|
947 |
+
$thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio['VBR_bitrate']; // to avoid confusion
|
948 |
+
}
|
949 |
+
break;
|
950 |
+
}
|
951 |
+
}
|
952 |
+
|
953 |
+
// End variable-bitrate headers
|
954 |
+
////////////////////////////////////////////////////////////////////////////////////
|
955 |
+
|
956 |
+
if ($recursivesearch) {
|
957 |
+
|
958 |
+
if (!getid3_mp3::RecursiveFrameScanning($fd, $ThisFileInfo, $offset, $nextframetestoffset, $ScanAsCBR)) {
|
959 |
+
return false;
|
960 |
+
}
|
961 |
+
|
962 |
+
}
|
963 |
+
|
964 |
+
|
965 |
+
//if (false) {
|
966 |
+
// // experimental side info parsing section - not returning anything useful yet
|
967 |
+
//
|
968 |
+
// $SideInfoBitstream = getid3_lib::BigEndian2Bin($SideInfoData);
|
969 |
+
// $SideInfoOffset = 0;
|
970 |
+
//
|
971 |
+
// if ($thisfile_mpeg_audio['version'] == '1') {
|
972 |
+
// if ($thisfile_mpeg_audio['channelmode'] == 'mono') {
|
973 |
+
// // MPEG-1 (mono)
|
974 |
+
// $thisfile_mpeg_audio['side_info']['main_data_begin'] = substr($SideInfoBitstream, $SideInfoOffset, 9);
|
975 |
+
// $SideInfoOffset += 9;
|
976 |
+
// $SideInfoOffset += 5;
|
977 |
+
// } else {
|
978 |
+
// // MPEG-1 (stereo, joint-stereo, dual-channel)
|
979 |
+
// $thisfile_mpeg_audio['side_info']['main_data_begin'] = substr($SideInfoBitstream, $SideInfoOffset, 9);
|
980 |
+
// $SideInfoOffset += 9;
|
981 |
+
// $SideInfoOffset += 3;
|
982 |
+
// }
|
983 |
+
// } else { // 2 or 2.5
|
984 |
+
// if ($thisfile_mpeg_audio['channelmode'] == 'mono') {
|
985 |
+
// // MPEG-2, MPEG-2.5 (mono)
|
986 |
+
// $thisfile_mpeg_audio['side_info']['main_data_begin'] = substr($SideInfoBitstream, $SideInfoOffset, 8);
|
987 |
+
// $SideInfoOffset += 8;
|
988 |
+
// $SideInfoOffset += 1;
|
989 |
+
// } else {
|
990 |
+
// // MPEG-2, MPEG-2.5 (stereo, joint-stereo, dual-channel)
|
991 |
+
// $thisfile_mpeg_audio['side_info']['main_data_begin'] = substr($SideInfoBitstream, $SideInfoOffset, 8);
|
992 |
+
// $SideInfoOffset += 8;
|
993 |
+
// $SideInfoOffset += 2;
|
994 |
+
// }
|
995 |
+
// }
|
996 |
+
//
|
997 |
+
// if ($thisfile_mpeg_audio['version'] == '1') {
|
998 |
+
// for ($channel = 0; $channel < $ThisFileInfo['audio']['channels']; $channel++) {
|
999 |
+
// for ($scfsi_band = 0; $scfsi_band < 4; $scfsi_band++) {
|
1000 |
+
// $thisfile_mpeg_audio['scfsi'][$channel][$scfsi_band] = substr($SideInfoBitstream, $SideInfoOffset, 1);
|
1001 |
+
// $SideInfoOffset += 2;
|
1002 |
+
// }
|
1003 |
+
// }
|
1004 |
+
// }
|
1005 |
+
// for ($granule = 0; $granule < (($thisfile_mpeg_audio['version'] == '1') ? 2 : 1); $granule++) {
|
1006 |
+
// for ($channel = 0; $channel < $ThisFileInfo['audio']['channels']; $channel++) {
|
1007 |
+
// $thisfile_mpeg_audio['part2_3_length'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 12);
|
1008 |
+
// $SideInfoOffset += 12;
|
1009 |
+
// $thisfile_mpeg_audio['big_values'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 9);
|
1010 |
+
// $SideInfoOffset += 9;
|
1011 |
+
// $thisfile_mpeg_audio['global_gain'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 8);
|
1012 |
+
// $SideInfoOffset += 8;
|
1013 |
+
// if ($thisfile_mpeg_audio['version'] == '1') {
|
1014 |
+
// $thisfile_mpeg_audio['scalefac_compress'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 4);
|
1015 |
+
// $SideInfoOffset += 4;
|
1016 |
+
// } else {
|
1017 |
+
// $thisfile_mpeg_audio['scalefac_compress'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 9);
|
1018 |
+
// $SideInfoOffset += 9;
|
1019 |
+
// }
|
1020 |
+
// $thisfile_mpeg_audio['window_switching_flag'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 1);
|
1021 |
+
// $SideInfoOffset += 1;
|
1022 |
+
//
|
1023 |
+
// if ($thisfile_mpeg_audio['window_switching_flag'][$granule][$channel] == '1') {
|
1024 |
+
//
|
1025 |
+
// $thisfile_mpeg_audio['block_type'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 2);
|
1026 |
+
// $SideInfoOffset += 2;
|
1027 |
+
// $thisfile_mpeg_audio['mixed_block_flag'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 1);
|
1028 |
+
// $SideInfoOffset += 1;
|
1029 |
+
//
|
1030 |
+
// for ($region = 0; $region < 2; $region++) {
|
1031 |
+
// $thisfile_mpeg_audio['table_select'][$granule][$channel][$region] = substr($SideInfoBitstream, $SideInfoOffset, 5);
|
1032 |
+
// $SideInfoOffset += 5;
|
1033 |
+
// }
|
1034 |
+
// $thisfile_mpeg_audio['table_select'][$granule][$channel][2] = 0;
|
1035 |
+
//
|
1036 |
+
// for ($window = 0; $window < 3; $window++) {
|
1037 |
+
// $thisfile_mpeg_audio['subblock_gain'][$granule][$channel][$window] = substr($SideInfoBitstream, $SideInfoOffset, 3);
|
1038 |
+
// $SideInfoOffset += 3;
|
1039 |
+
// }
|
1040 |
+
//
|
1041 |
+
// } else {
|
1042 |
+
//
|
1043 |
+
// for ($region = 0; $region < 3; $region++) {
|
1044 |
+
// $thisfile_mpeg_audio['table_select'][$granule][$channel][$region] = substr($SideInfoBitstream, $SideInfoOffset, 5);
|
1045 |
+
// $SideInfoOffset += 5;
|
1046 |
+
// }
|
1047 |
+
//
|
1048 |
+
// $thisfile_mpeg_audio['region0_count'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 4);
|
1049 |
+
// $SideInfoOffset += 4;
|
1050 |
+
// $thisfile_mpeg_audio['region1_count'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 3);
|
1051 |
+
// $SideInfoOffset += 3;
|
1052 |
+
// $thisfile_mpeg_audio['block_type'][$granule][$channel] = 0;
|
1053 |
+
// }
|
1054 |
+
//
|
1055 |
+
// if ($thisfile_mpeg_audio['version'] == '1') {
|
1056 |
+
// $thisfile_mpeg_audio['preflag'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 1);
|
1057 |
+
// $SideInfoOffset += 1;
|
1058 |
+
// }
|
1059 |
+
// $thisfile_mpeg_audio['scalefac_scale'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 1);
|
1060 |
+
// $SideInfoOffset += 1;
|
1061 |
+
// $thisfile_mpeg_audio['count1table_select'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 1);
|
1062 |
+
// $SideInfoOffset += 1;
|
1063 |
+
// }
|
1064 |
+
// }
|
1065 |
+
//}
|
1066 |
+
|
1067 |
+
return true;
|
1068 |
+
}
|
1069 |
+
|
1070 |
+
function RecursiveFrameScanning(&$fd, &$ThisFileInfo, &$offset, &$nextframetestoffset, $ScanAsCBR) {
|
1071 |
+
for ($i = 0; $i < GETID3_MP3_VALID_CHECK_FRAMES; $i++) {
|
1072 |
+
// check next GETID3_MP3_VALID_CHECK_FRAMES frames for validity, to make sure we haven't run across a false synch
|
1073 |
+
if (($nextframetestoffset + 4) >= $ThisFileInfo['avdataend']) {
|
1074 |
+
// end of file
|
1075 |
+
return true;
|
1076 |
+
}
|
1077 |
+
|
1078 |
+
$nextframetestarray = array('error'=>'', 'warning'=>'', 'avdataend'=>$ThisFileInfo['avdataend'], 'avdataoffset'=>$ThisFileInfo['avdataoffset']);
|
1079 |
+
if (getid3_mp3::decodeMPEGaudioHeader($fd, $nextframetestoffset, $nextframetestarray, false)) {
|
1080 |
+
if ($ScanAsCBR) {
|
1081 |
+
// force CBR mode, used for trying to pick out invalid audio streams with
|
1082 |
+
// valid(?) VBR headers, or VBR streams with no VBR header
|
1083 |
+
if (!isset($nextframetestarray['mpeg']['audio']['bitrate']) || !isset($ThisFileInfo['mpeg']['audio']['bitrate']) || ($nextframetestarray['mpeg']['audio']['bitrate'] != $ThisFileInfo['mpeg']['audio']['bitrate'])) {
|
1084 |
+
return false;
|
1085 |
+
}
|
1086 |
+
}
|
1087 |
+
|
1088 |
+
|
1089 |
+
// next frame is OK, get ready to check the one after that
|
1090 |
+
if (isset($nextframetestarray['mpeg']['audio']['framelength']) && ($nextframetestarray['mpeg']['audio']['framelength'] > 0)) {
|
1091 |
+
$nextframetestoffset += $nextframetestarray['mpeg']['audio']['framelength'];
|
1092 |
+
} else {
|
1093 |
+
$ThisFileInfo['error'][] = 'Frame at offset ('.$offset.') is has an invalid frame length.';
|
1094 |
+
return false;
|
1095 |
+
}
|
1096 |
+
|
1097 |
+
} else {
|
1098 |
+
|
1099 |
+
// next frame is not valid, note the error and fail, so scanning can contiue for a valid frame sequence
|
1100 |
+
$ThisFileInfo['error'][] = 'Frame at offset ('.$offset.') is valid, but the next one at ('.$nextframetestoffset.') is not.';
|
1101 |
+
|
1102 |
+
return false;
|
1103 |
+
}
|
1104 |
+
}
|
1105 |
+
return true;
|
1106 |
+
}
|
1107 |
+
|
1108 |
+
function FreeFormatFrameLength($fd, $offset, &$ThisFileInfo, $deepscan=false) {
|
1109 |
+
fseek($fd, $offset, SEEK_SET);
|
1110 |
+
$MPEGaudioData = fread($fd, 32768);
|
1111 |
+
|
1112 |
+
$SyncPattern1 = substr($MPEGaudioData, 0, 4);
|
1113 |
+
// may be different pattern due to padding
|
1114 |
+
$SyncPattern2 = $SyncPattern1{0}.$SyncPattern1{1}.chr(ord($SyncPattern1{2}) | 0x02).$SyncPattern1{3};
|
1115 |
+
if ($SyncPattern2 === $SyncPattern1) {
|
1116 |
+
$SyncPattern2 = $SyncPattern1{0}.$SyncPattern1{1}.chr(ord($SyncPattern1{2}) & 0xFD).$SyncPattern1{3};
|
1117 |
+
}
|
1118 |
+
|
1119 |
+
$framelength = false;
|
1120 |
+
$framelength1 = strpos($MPEGaudioData, $SyncPattern1, 4);
|
1121 |
+
$framelength2 = strpos($MPEGaudioData, $SyncPattern2, 4);
|
1122 |
+
if ($framelength1 > 4) {
|
1123 |
+
$framelength = $framelength1;
|
1124 |
+
}
|
1125 |
+
if (($framelength2 > 4) && ($framelength2 < $framelength1)) {
|
1126 |
+
$framelength = $framelength2;
|
1127 |
+
}
|
1128 |
+
if (!$framelength) {
|
1129 |
+
|
1130 |
+
// LAME 3.88 has a different value for modeextension on the first frame vs the rest
|
1131 |
+
$framelength1 = strpos($MPEGaudioData, substr($SyncPattern1, 0, 3), 4);
|
1132 |
+
$framelength2 = strpos($MPEGaudioData, substr($SyncPattern2, 0, 3), 4);
|
1133 |
+
|
1134 |
+
if ($framelength1 > 4) {
|
1135 |
+
$framelength = $framelength1;
|
1136 |
+
}
|
1137 |
+
if (($framelength2 > 4) && ($framelength2 < $framelength1)) {
|
1138 |
+
$framelength = $framelength2;
|
1139 |
+
}
|
1140 |
+
if (!$framelength) {
|
1141 |
+
$ThisFileInfo['error'][] = 'Cannot find next free-format synch pattern ('.getid3_lib::PrintHexBytes($SyncPattern1).' or '.getid3_lib::PrintHexBytes($SyncPattern2).') after offset '.$offset;
|
1142 |
+
return false;
|
1143 |
+
} else {
|
1144 |
+
$ThisFileInfo['warning'][] = 'ModeExtension varies between first frame and other frames (known free-format issue in LAME 3.88)';
|
1145 |
+
$ThisFileInfo['audio']['codec'] = 'LAME';
|
1146 |
+
$ThisFileInfo['audio']['encoder'] = 'LAME3.88';
|
1147 |
+
$SyncPattern1 = substr($SyncPattern1, 0, 3);
|
1148 |
+
$SyncPattern2 = substr($SyncPattern2, 0, 3);
|
1149 |
+
}
|
1150 |
+
}
|
1151 |
+
|
1152 |
+
if ($deepscan) {
|
1153 |
+
|
1154 |
+
$ActualFrameLengthValues = array();
|
1155 |
+
$nextoffset = $offset + $framelength;
|
1156 |
+
while ($nextoffset < ($ThisFileInfo['avdataend'] - 6)) {
|
1157 |
+
fseek($fd, $nextoffset - 1, SEEK_SET);
|
1158 |
+
$NextSyncPattern = fread($fd, 6);
|
1159 |
+
if ((substr($NextSyncPattern, 1, strlen($SyncPattern1)) == $SyncPattern1) || (substr($NextSyncPattern, 1, strlen($SyncPattern2)) == $SyncPattern2)) {
|
1160 |
+
// good - found where expected
|
1161 |
+
$ActualFrameLengthValues[] = $framelength;
|
1162 |
+
} elseif ((substr($NextSyncPattern, 0, strlen($SyncPattern1)) == $SyncPattern1) || (substr($NextSyncPattern, 0, strlen($SyncPattern2)) == $SyncPattern2)) {
|
1163 |
+
// ok - found one byte earlier than expected (last frame wasn't padded, first frame was)
|
1164 |
+
$ActualFrameLengthValues[] = ($framelength - 1);
|
1165 |
+
$nextoffset--;
|
1166 |
+
} elseif ((substr($NextSyncPattern, 2, strlen($SyncPattern1)) == $SyncPattern1) || (substr($NextSyncPattern, 2, strlen($SyncPattern2)) == $SyncPattern2)) {
|
1167 |
+
// ok - found one byte later than expected (last frame was padded, first frame wasn't)
|
1168 |
+
$ActualFrameLengthValues[] = ($framelength + 1);
|
1169 |
+
$nextoffset++;
|
1170 |
+
} else {
|
1171 |
+
$ThisFileInfo['error'][] = 'Did not find expected free-format sync pattern at offset '.$nextoffset;
|
1172 |
+
return false;
|
1173 |
+
}
|
1174 |
+
$nextoffset += $framelength;
|
1175 |
+
}
|
1176 |
+
if (count($ActualFrameLengthValues) > 0) {
|
1177 |
+
$framelength = intval(round(array_sum($ActualFrameLengthValues) / count($ActualFrameLengthValues)));
|
1178 |
+
}
|
1179 |
+
}
|
1180 |
+
return $framelength;
|
1181 |
+
}
|
1182 |
+
|
1183 |
+
function getOnlyMPEGaudioInfoBruteForce($fd, &$ThisFileInfo) {
|
1184 |
+
|
1185 |
+
$MPEGaudioHeaderDecodeCache = array();
|
1186 |
+
$MPEGaudioHeaderValidCache = array();
|
1187 |
+
$MPEGaudioHeaderLengthCache = array();
|
1188 |
+
$MPEGaudioVersionLookup = getid3_mp3::MPEGaudioVersionArray();
|
1189 |
+
$MPEGaudioLayerLookup = getid3_mp3::MPEGaudioLayerArray();
|
1190 |
+
$MPEGaudioBitrateLookup = getid3_mp3::MPEGaudioBitrateArray();
|
1191 |
+
$MPEGaudioFrequencyLookup = getid3_mp3::MPEGaudioFrequencyArray();
|
1192 |
+
$MPEGaudioChannelModeLookup = getid3_mp3::MPEGaudioChannelModeArray();
|
1193 |
+
$MPEGaudioModeExtensionLookup = getid3_mp3::MPEGaudioModeExtensionArray();
|
1194 |
+
$MPEGaudioEmphasisLookup = getid3_mp3::MPEGaudioEmphasisArray();
|
1195 |
+
$LongMPEGversionLookup = array();
|
1196 |
+
$LongMPEGlayerLookup = array();
|
1197 |
+
$LongMPEGbitrateLookup = array();
|
1198 |
+
$LongMPEGpaddingLookup = array();
|
1199 |
+
$LongMPEGfrequencyLookup = array();
|
1200 |
+
|
1201 |
+
$Distribution['bitrate'] = array();
|
1202 |
+
$Distribution['frequency'] = array();
|
1203 |
+
$Distribution['layer'] = array();
|
1204 |
+
$Distribution['version'] = array();
|
1205 |
+
$Distribution['padding'] = array();
|
1206 |
+
|
1207 |
+
fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
|
1208 |
+
|
1209 |
+
$previousvalidframe = $ThisFileInfo['avdataoffset'];
|
1210 |
+
while (ftell($fd) < $ThisFileInfo['avdataend']) {
|
1211 |
+
set_time_limit(30);
|
1212 |
+
$head4 = fread($fd, 4);
|
1213 |
+
if (strlen($head4) < 4) {
|
1214 |
+
break;
|
1215 |
+
}
|
1216 |
+
if ($head4{0} != "\xFF") {
|
1217 |
+
for ($i = 1; $i < 4; $i++) {
|
1218 |
+
if ($head4{$i} == "\xFF") {
|
1219 |
+
fseek($fd, $i - 4, SEEK_CUR);
|
1220 |
+
continue 2;
|
1221 |
+
}
|
1222 |
+
}
|
1223 |
+
continue;
|
1224 |
+
}
|
1225 |
+
if (!isset($MPEGaudioHeaderDecodeCache[$head4])) {
|
1226 |
+
$MPEGaudioHeaderDecodeCache[$head4] = getid3_mp3::MPEGaudioHeaderDecode($head4);
|
1227 |
+
}
|
1228 |
+
if (!isset($MPEGaudioHeaderValidCache[$head4])) {
|
1229 |
+
$MPEGaudioHeaderValidCache[$head4] = getid3_mp3::MPEGaudioHeaderValid($MPEGaudioHeaderDecodeCache[$head4], false, false);
|
1230 |
+
}
|
1231 |
+
if ($MPEGaudioHeaderValidCache[$head4]) {
|
1232 |
+
|
1233 |
+
if (!isset($MPEGaudioHeaderLengthCache[$head4])) {
|
1234 |
+
$LongMPEGversionLookup[$head4] = $MPEGaudioVersionLookup[$MPEGaudioHeaderDecodeCache[$head4]['version']];
|
1235 |
+
$LongMPEGlayerLookup[$head4] = $MPEGaudioLayerLookup[$MPEGaudioHeaderDecodeCache[$head4]['layer']];
|
1236 |
+
$LongMPEGbitrateLookup[$head4] = $MPEGaudioBitrateLookup[$LongMPEGversionLookup[$head4]][$LongMPEGlayerLookup[$head4]][$MPEGaudioHeaderDecodeCache[$head4]['bitrate']];
|
1237 |
+
$LongMPEGpaddingLookup[$head4] = (bool) $MPEGaudioHeaderDecodeCache[$head4]['padding'];
|
1238 |
+
$LongMPEGfrequencyLookup[$head4] = $MPEGaudioFrequencyLookup[$LongMPEGversionLookup[$head4]][$MPEGaudioHeaderDecodeCache[$head4]['sample_rate']];
|
1239 |
+
$MPEGaudioHeaderLengthCache[$head4] = getid3_mp3::MPEGaudioFrameLength(
|
1240 |
+
$LongMPEGbitrateLookup[$head4],
|
1241 |
+
$LongMPEGversionLookup[$head4],
|
1242 |
+
$LongMPEGlayerLookup[$head4],
|
1243 |
+
$LongMPEGpaddingLookup[$head4],
|
1244 |
+
$LongMPEGfrequencyLookup[$head4]);
|
1245 |
+
}
|
1246 |
+
if ($MPEGaudioHeaderLengthCache[$head4] > 4) {
|
1247 |
+
$WhereWeWere = ftell($fd);
|
1248 |
+
fseek($fd, $MPEGaudioHeaderLengthCache[$head4] - 4, SEEK_CUR);
|
1249 |
+
$next4 = fread($fd, 4);
|
1250 |
+
if ($next4{0} == "\xFF") {
|
1251 |
+
if (!isset($MPEGaudioHeaderDecodeCache[$next4])) {
|
1252 |
+
$MPEGaudioHeaderDecodeCache[$next4] = getid3_mp3::MPEGaudioHeaderDecode($next4);
|
1253 |
+
}
|
1254 |
+
if (!isset($MPEGaudioHeaderValidCache[$next4])) {
|
1255 |
+
$MPEGaudioHeaderValidCache[$next4] = getid3_mp3::MPEGaudioHeaderValid($MPEGaudioHeaderDecodeCache[$next4], false, false);
|
1256 |
+
}
|
1257 |
+
if ($MPEGaudioHeaderValidCache[$next4]) {
|
1258 |
+
fseek($fd, -4, SEEK_CUR);
|
1259 |
+
|
1260 |
+
@$Distribution['bitrate'][$LongMPEGbitrateLookup[$head4]]++;
|
1261 |
+
@$Distribution['layer'][$LongMPEGlayerLookup[$head4]]++;
|
1262 |
+
@$Distribution['version'][$LongMPEGversionLookup[$head4]]++;
|
1263 |
+
@$Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])]++;
|
1264 |
+
@$Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]]++;
|
1265 |
+
continue;
|
1266 |
+
}
|
1267 |
+
}
|
1268 |
+
unset($next4);
|
1269 |
+
fseek($fd, $WhereWeWere - 3, SEEK_SET);
|
1270 |
+
}
|
1271 |
+
|
1272 |
+
}
|
1273 |
+
}
|
1274 |
+
foreach ($Distribution as $key => $value) {
|
1275 |
+
ksort($Distribution[$key], SORT_NUMERIC);
|
1276 |
+
}
|
1277 |
+
ksort($Distribution['version'], SORT_STRING);
|
1278 |
+
$ThisFileInfo['mpeg']['audio']['bitrate_distribution'] = $Distribution['bitrate'];
|
1279 |
+
$ThisFileInfo['mpeg']['audio']['frequency_distribution'] = $Distribution['frequency'];
|
1280 |
+
$ThisFileInfo['mpeg']['audio']['layer_distribution'] = $Distribution['layer'];
|
1281 |
+
$ThisFileInfo['mpeg']['audio']['version_distribution'] = $Distribution['version'];
|
1282 |
+
$ThisFileInfo['mpeg']['audio']['padding_distribution'] = $Distribution['padding'];
|
1283 |
+
if (count($Distribution['version']) > 1) {
|
1284 |
+
$ThisFileInfo['error'][] = 'Corrupt file - more than one MPEG version detected';
|
1285 |
+
}
|
1286 |
+
if (count($Distribution['layer']) > 1) {
|
1287 |
+
$ThisFileInfo['error'][] = 'Corrupt file - more than one MPEG layer detected';
|
1288 |
+
}
|
1289 |
+
if (count($Distribution['frequency']) > 1) {
|
1290 |
+
$ThisFileInfo['error'][] = 'Corrupt file - more than one MPEG sample rate detected';
|
1291 |
+
}
|
1292 |
+
|
1293 |
+
|
1294 |
+
$bittotal = 0;
|
1295 |
+
foreach ($Distribution['bitrate'] as $bitratevalue => $bitratecount) {
|
1296 |
+
if ($bitratevalue != 'free') {
|
1297 |
+
$bittotal += ($bitratevalue * $bitratecount);
|
1298 |
+
}
|
1299 |
+
}
|
1300 |
+
$ThisFileInfo['mpeg']['audio']['frame_count'] = array_sum($Distribution['bitrate']);
|
1301 |
+
if ($ThisFileInfo['mpeg']['audio']['frame_count'] == 0) {
|
1302 |
+
$ThisFileInfo['error'][] = 'no MPEG audio frames found';
|
1303 |
+
return false;
|
1304 |
+
}
|
1305 |
+
$ThisFileInfo['mpeg']['audio']['bitrate'] = ($bittotal / $ThisFileInfo['mpeg']['audio']['frame_count']);
|
1306 |
+
$ThisFileInfo['mpeg']['audio']['bitrate_mode'] = ((count($Distribution['bitrate']) > 0) ? 'vbr' : 'cbr');
|
1307 |
+
$ThisFileInfo['mpeg']['audio']['sample_rate'] = getid3_lib::array_max($Distribution['frequency'], true);
|
1308 |
+
|
1309 |
+
$ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['mpeg']['audio']['bitrate'];
|
1310 |
+
$ThisFileInfo['audio']['bitrate_mode'] = $ThisFileInfo['mpeg']['audio']['bitrate_mode'];
|
1311 |
+
$ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['mpeg']['audio']['sample_rate'];
|
1312 |
+
$ThisFileInfo['audio']['dataformat'] = 'mp'.getid3_lib::array_max($Distribution['layer'], true);
|
1313 |
+
$ThisFileInfo['fileformat'] = $ThisFileInfo['audio']['dataformat'];
|
1314 |
+
|
1315 |
+
return true;
|
1316 |
+
}
|
1317 |
+
|
1318 |
+
|
1319 |
+
function getOnlyMPEGaudioInfo($fd, &$ThisFileInfo, $avdataoffset, $BitrateHistogram=false) {
|
1320 |
+
|
1321 |
+
// looks for synch, decodes MPEG audio header
|
1322 |
+
|
1323 |
+
static $MPEGaudioVersionLookup;
|
1324 |
+
static $MPEGaudioLayerLookup;
|
1325 |
+
static $MPEGaudioBitrateLookup;
|
1326 |
+
if (empty($MPEGaudioVersionLookup)) {
|
1327 |
+
$MPEGaudioVersionLookup = getid3_mp3::MPEGaudioVersionArray();
|
1328 |
+
$MPEGaudioLayerLookup = getid3_mp3::MPEGaudioLayerArray();
|
1329 |
+
$MPEGaudioBitrateLookup = getid3_mp3::MPEGaudioBitrateArray();
|
1330 |
+
|
1331 |
+
}
|
1332 |
+
|
1333 |
+
fseek($fd, $avdataoffset, SEEK_SET);
|
1334 |
+
$sync_seek_buffer_size = min(128 * 1024, $ThisFileInfo['avdataend'] - $avdataoffset);
|
1335 |
+
$header = fread($fd, $sync_seek_buffer_size);
|
1336 |
+
$sync_seek_buffer_size = strlen($header);
|
1337 |
+
$SynchSeekOffset = 0;
|
1338 |
+
while ($SynchSeekOffset < $sync_seek_buffer_size) {
|
1339 |
+
|
1340 |
+
if ((($avdataoffset + $SynchSeekOffset) < $ThisFileInfo['avdataend']) && !feof($fd)) {
|
1341 |
+
|
1342 |
+
if ($SynchSeekOffset > $sync_seek_buffer_size) {
|
1343 |
+
// if a synch's not found within the first 128k bytes, then give up
|
1344 |
+
$ThisFileInfo['error'][] = 'Could not find valid MPEG audio synch within the first '.round($sync_seek_buffer_size / 1024).'kB';
|
1345 |
+
if (isset($ThisFileInfo['audio']['bitrate'])) {
|
1346 |
+
unset($ThisFileInfo['audio']['bitrate']);
|
1347 |
+
}
|
1348 |
+
if (isset($ThisFileInfo['mpeg']['audio'])) {
|
1349 |
+
unset($ThisFileInfo['mpeg']['audio']);
|
1350 |
+
}
|
1351 |
+
if (empty($ThisFileInfo['mpeg'])) {
|
1352 |
+
unset($ThisFileInfo['mpeg']);
|
1353 |
+
}
|
1354 |
+
return false;
|
1355 |
+
|
1356 |
+
} elseif (feof($fd)) {
|
1357 |
+
|
1358 |
+
$ThisFileInfo['error'][] = 'Could not find valid MPEG audio synch before end of file';
|
1359 |
+
if (isset($ThisFileInfo['audio']['bitrate'])) {
|
1360 |
+
unset($ThisFileInfo['audio']['bitrate']);
|
1361 |
+
}
|
1362 |
+
if (isset($ThisFileInfo['mpeg']['audio'])) {
|
1363 |
+
unset($ThisFileInfo['mpeg']['audio']);
|
1364 |
+
}
|
1365 |
+
if (isset($ThisFileInfo['mpeg']) && (!is_array($ThisFileInfo['mpeg']) || (count($ThisFileInfo['mpeg']) == 0))) {
|
1366 |
+
unset($ThisFileInfo['mpeg']);
|
1367 |
+
}
|
1368 |
+
return false;
|
1369 |
+
}
|
1370 |
+
}
|
1371 |
+
|
1372 |
+
if (($SynchSeekOffset + 1) >= strlen($header)) {
|
1373 |
+
$ThisFileInfo['error'][] = 'Could not find valid MPEG synch before end of file';
|
1374 |
+
return false;
|
1375 |
+
}
|
1376 |
+
|
1377 |
+
if (($header{$SynchSeekOffset} == "\xFF") && ($header{($SynchSeekOffset + 1)} > "\xE0")) { // synch detected
|
1378 |
+
|
1379 |
+
if (!isset($FirstFrameThisfileInfo) && !isset($ThisFileInfo['mpeg']['audio'])) {
|
1380 |
+
$FirstFrameThisfileInfo = $ThisFileInfo;
|
1381 |
+
$FirstFrameAVDataOffset = $avdataoffset + $SynchSeekOffset;
|
1382 |
+
if (!getid3_mp3::decodeMPEGaudioHeader($fd, $avdataoffset + $SynchSeekOffset, $FirstFrameThisfileInfo, false)) {
|
1383 |
+
// if this is the first valid MPEG-audio frame, save it in case it's a VBR header frame and there's
|
1384 |
+
// garbage between this frame and a valid sequence of MPEG-audio frames, to be restored below
|
1385 |
+
unset($FirstFrameThisfileInfo);
|
1386 |
+
}
|
1387 |
+
}
|
1388 |
+
|
1389 |
+
$dummy = $ThisFileInfo; // only overwrite real data if valid header found
|
1390 |
+
if (getid3_mp3::decodeMPEGaudioHeader($fd, $avdataoffset + $SynchSeekOffset, $dummy, true)) {
|
1391 |
+
$ThisFileInfo = $dummy;
|
1392 |
+
$ThisFileInfo['avdataoffset'] = $avdataoffset + $SynchSeekOffset;
|
1393 |
+
switch ($ThisFileInfo['fileformat']) {
|
1394 |
+
case '':
|
1395 |
+
case 'id3':
|
1396 |
+
case 'ape':
|
1397 |
+
case 'mp3':
|
1398 |
+
$ThisFileInfo['fileformat'] = 'mp3';
|
1399 |
+
$ThisFileInfo['audio']['dataformat'] = 'mp3';
|
1400 |
+
break;
|
1401 |
+
}
|
1402 |
+
if (isset($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode']) && ($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode'] == 'vbr')) {
|
1403 |
+
if (!(abs($ThisFileInfo['audio']['bitrate'] - $FirstFrameThisfileInfo['audio']['bitrate']) <= 1)) {
|
1404 |
+
// If there is garbage data between a valid VBR header frame and a sequence
|
1405 |
+
// of valid MPEG-audio frames the VBR data is no longer discarded.
|
1406 |
+
$ThisFileInfo = $FirstFrameThisfileInfo;
|
1407 |
+
$ThisFileInfo['avdataoffset'] = $FirstFrameAVDataOffset;
|
1408 |
+
$ThisFileInfo['fileformat'] = 'mp3';
|
1409 |
+
$ThisFileInfo['audio']['dataformat'] = 'mp3';
|
1410 |
+
$dummy = $ThisFileInfo;
|
1411 |
+
unset($dummy['mpeg']['audio']);
|
1412 |
+
$GarbageOffsetStart = $FirstFrameAVDataOffset + $FirstFrameThisfileInfo['mpeg']['audio']['framelength'];
|
1413 |
+
$GarbageOffsetEnd = $avdataoffset + $SynchSeekOffset;
|
1414 |
+
if (getid3_mp3::decodeMPEGaudioHeader($fd, $GarbageOffsetEnd, $dummy, true, true)) {
|
1415 |
+
|
1416 |
+
$ThisFileInfo = $dummy;
|
1417 |
+
$ThisFileInfo['avdataoffset'] = $GarbageOffsetEnd;
|
1418 |
+
$ThisFileInfo['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;
|
1419 |
+
|
1420 |
+
} else {
|
1421 |
+
|
1422 |
+
$ThisFileInfo['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.')';
|
1423 |
+
|
1424 |
+
}
|
1425 |
+
}
|
1426 |
+
}
|
1427 |
+
if (isset($ThisFileInfo['mpeg']['audio']['bitrate_mode']) && ($ThisFileInfo['mpeg']['audio']['bitrate_mode'] == 'vbr') && !isset($ThisFileInfo['mpeg']['audio']['VBR_method'])) {
|
1428 |
+
// VBR file with no VBR header
|
1429 |
+
$BitrateHistogram = true;
|
1430 |
+
}
|
1431 |
+
|
1432 |
+
if ($BitrateHistogram) {
|
1433 |
+
|
1434 |
+
$ThisFileInfo['mpeg']['audio']['stereo_distribution'] = array('stereo'=>0, 'joint stereo'=>0, 'dual channel'=>0, 'mono'=>0);
|
1435 |
+
$ThisFileInfo['mpeg']['audio']['version_distribution'] = array('1'=>0, '2'=>0, '2.5'=>0);
|
1436 |
+
|
1437 |
+
if ($ThisFileInfo['mpeg']['audio']['version'] == '1') {
|
1438 |
+
if ($ThisFileInfo['mpeg']['audio']['layer'] == 3) {
|
1439 |
+
$ThisFileInfo['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 32000=>0, 40000=>0, 48000=>0, 56000=>0, 64000=>0, 80000=>0, 96000=>0, 112000=>0, 128000=>0, 160000=>0, 192000=>0, 224000=>0, 256000=>0, 320000=>0);
|
1440 |
+
} elseif ($ThisFileInfo['mpeg']['audio']['layer'] == 2) {
|
1441 |
+
$ThisFileInfo['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 32000=>0, 48000=>0, 56000=>0, 64000=>0, 80000=>0, 96000=>0, 112000=>0, 128000=>0, 160000=>0, 192000=>0, 224000=>0, 256000=>0, 320000=>0, 384000=>0);
|
1442 |
+
} elseif ($ThisFileInfo['mpeg']['audio']['layer'] == 1) {
|
1443 |
+
$ThisFileInfo['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 32000=>0, 64000=>0, 96000=>0, 128000=>0, 160000=>0, 192000=>0, 224000=>0, 256000=>0, 288000=>0, 320000=>0, 352000=>0, 384000=>0, 416000=>0, 448000=>0);
|
1444 |
+
}
|
1445 |
+
} elseif ($ThisFileInfo['mpeg']['audio']['layer'] == 1) {
|
1446 |
+
$ThisFileInfo['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 32000=>0, 48000=>0, 56000=>0, 64000=>0, 80000=>0, 96000=>0, 112000=>0, 128000=>0, 144000=>0, 160000=>0, 176000=>0, 192000=>0, 224000=>0, 256000=>0);
|
1447 |
+
} else {
|
1448 |
+
$ThisFileInfo['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 8000=>0, 16000=>0, 24000=>0, 32000=>0, 40000=>0, 48000=>0, 56000=>0, 64000=>0, 80000=>0, 96000=>0, 112000=>0, 128000=>0, 144000=>0, 160000=>0);
|
1449 |
+
}
|
1450 |
+
|
1451 |
+
$dummy = array('error'=>$ThisFileInfo['error'], 'warning'=>$ThisFileInfo['warning'], 'avdataend'=>$ThisFileInfo['avdataend'], 'avdataoffset'=>$ThisFileInfo['avdataoffset']);
|
1452 |
+
$synchstartoffset = $ThisFileInfo['avdataoffset'];
|
1453 |
+
|
1454 |
+
$FastMode = false;
|
1455 |
+
$SynchErrorsFound = 0;
|
1456 |
+
while (getid3_mp3::decodeMPEGaudioHeader($fd, $synchstartoffset, $dummy, false, false, $FastMode)) {
|
1457 |
+
$FastMode = true;
|
1458 |
+
$thisframebitrate = $MPEGaudioBitrateLookup[$MPEGaudioVersionLookup[$dummy['mpeg']['audio']['raw']['version']]][$MPEGaudioLayerLookup[$dummy['mpeg']['audio']['raw']['layer']]][$dummy['mpeg']['audio']['raw']['bitrate']];
|
1459 |
+
|
1460 |
+
if (empty($dummy['mpeg']['audio']['framelength'])) {
|
1461 |
+
$SynchErrorsFound++;
|
1462 |
+
} else {
|
1463 |
+
@$ThisFileInfo['mpeg']['audio']['bitrate_distribution'][$thisframebitrate]++;
|
1464 |
+
@$ThisFileInfo['mpeg']['audio']['stereo_distribution'][$dummy['mpeg']['audio']['channelmode']]++;
|
1465 |
+
@$ThisFileInfo['mpeg']['audio']['version_distribution'][$dummy['mpeg']['audio']['version']]++;
|
1466 |
+
|
1467 |
+
$synchstartoffset += $dummy['mpeg']['audio']['framelength'];
|
1468 |
+
}
|
1469 |
+
}
|
1470 |
+
if ($SynchErrorsFound > 0) {
|
1471 |
+
$ThisFileInfo['warning'][] = 'Found '.$SynchErrorsFound.' synch errors in histogram analysis';
|
1472 |
+
//return false;
|
1473 |
+
}
|
1474 |
+
|
1475 |
+
$bittotal = 0;
|
1476 |
+
$framecounter = 0;
|
1477 |
+
foreach ($ThisFileInfo['mpeg']['audio']['bitrate_distribution'] as $bitratevalue => $bitratecount) {
|
1478 |
+
$framecounter += $bitratecount;
|
1479 |
+
if ($bitratevalue != 'free') {
|
1480 |
+
$bittotal += ($bitratevalue * $bitratecount);
|
1481 |
+
}
|
1482 |
+
}
|
1483 |
+
if ($framecounter == 0) {
|
1484 |
+
$ThisFileInfo['error'][] = 'Corrupt MP3 file: framecounter == zero';
|
1485 |
+
return false;
|
1486 |
+
}
|
1487 |
+
$ThisFileInfo['mpeg']['audio']['frame_count'] = $framecounter;
|
1488 |
+
$ThisFileInfo['mpeg']['audio']['bitrate'] = ($bittotal / $framecounter);
|
1489 |
+
|
1490 |
+
$ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['mpeg']['audio']['bitrate'];
|
1491 |
+
|
1492 |
+
|
1493 |
+
// Definitively set VBR vs CBR, even if the Xing/LAME/VBRI header says differently
|
1494 |
+
$distinct_bitrates = 0;
|
1495 |
+
foreach ($ThisFileInfo['mpeg']['audio']['bitrate_distribution'] as $bitrate_value => $bitrate_count) {
|
1496 |
+
if ($bitrate_count > 0) {
|
1497 |
+
$distinct_bitrates++;
|
1498 |
+
}
|
1499 |
+
}
|
1500 |
+
if ($distinct_bitrates > 1) {
|
1501 |
+
$ThisFileInfo['mpeg']['audio']['bitrate_mode'] = 'vbr';
|
1502 |
+
} else {
|
1503 |
+
$ThisFileInfo['mpeg']['audio']['bitrate_mode'] = 'cbr';
|
1504 |
+
}
|
1505 |
+
$ThisFileInfo['audio']['bitrate_mode'] = $ThisFileInfo['mpeg']['audio']['bitrate_mode'];
|
1506 |
+
|
1507 |
+
}
|
1508 |
+
|
1509 |
+
break; // exit while()
|
1510 |
+
}
|
1511 |
+
}
|
1512 |
+
|
1513 |
+
$SynchSeekOffset++;
|
1514 |
+
if (($avdataoffset + $SynchSeekOffset) >= $ThisFileInfo['avdataend']) {
|
1515 |
+
// end of file/data
|
1516 |
+
|
1517 |
+
if (empty($ThisFileInfo['mpeg']['audio'])) {
|
1518 |
+
|
1519 |
+
$ThisFileInfo['error'][] = 'could not find valid MPEG synch before end of file';
|
1520 |
+
if (isset($ThisFileInfo['audio']['bitrate'])) {
|
1521 |
+
unset($ThisFileInfo['audio']['bitrate']);
|
1522 |
+
}
|
1523 |
+
if (isset($ThisFileInfo['mpeg']['audio'])) {
|
1524 |
+
unset($ThisFileInfo['mpeg']['audio']);
|
1525 |
+
}
|
1526 |
+
if (isset($ThisFileInfo['mpeg']) && (!is_array($ThisFileInfo['mpeg']) || empty($ThisFileInfo['mpeg']))) {
|
1527 |
+
unset($ThisFileInfo['mpeg']);
|
1528 |
+
}
|
1529 |
+
return false;
|
1530 |
+
|
1531 |
+
}
|
1532 |
+
break;
|
1533 |
+
}
|
1534 |
+
|
1535 |
+
}
|
1536 |
+
$ThisFileInfo['audio']['channels'] = $ThisFileInfo['mpeg']['audio']['channels'];
|
1537 |
+
$ThisFileInfo['audio']['channelmode'] = $ThisFileInfo['mpeg']['audio']['channelmode'];
|
1538 |
+
$ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['mpeg']['audio']['sample_rate'];
|
1539 |
+
return true;
|
1540 |
+
}
|
1541 |
+
|
1542 |
+
|
1543 |
+
function MPEGaudioVersionArray() {
|
1544 |
+
static $MPEGaudioVersion = array('2.5', false, '2', '1');
|
1545 |
+
return $MPEGaudioVersion;
|
1546 |
+
}
|
1547 |
+
|
1548 |
+
function MPEGaudioLayerArray() {
|
1549 |
+
static $MPEGaudioLayer = array(false, 3, 2, 1);
|
1550 |
+
return $MPEGaudioLayer;
|
1551 |
+
}
|
1552 |
+
|
1553 |
+
function MPEGaudioBitrateArray() {
|
1554 |
+
static $MPEGaudioBitrate;
|
1555 |
+
if (empty($MPEGaudioBitrate)) {
|
1556 |
+
$MPEGaudioBitrate = array (
|
1557 |
+
'1' => array (1 => array('free', 32000, 64000, 96000, 128000, 160000, 192000, 224000, 256000, 288000, 320000, 352000, 384000, 416000, 448000),
|
1558 |
+
2 => array('free', 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, 384000),
|
1559 |
+
3 => array('free', 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000)
|
1560 |
+
),
|
1561 |
+
|
1562 |
+
'2' => array (1 => array('free', 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 176000, 192000, 224000, 256000),
|
1563 |
+
2 => array('free', 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000),
|
1564 |
+
)
|
1565 |
+
);
|
1566 |
+
$MPEGaudioBitrate['2'][3] = $MPEGaudioBitrate['2'][2];
|
1567 |
+
$MPEGaudioBitrate['2.5'] = $MPEGaudioBitrate['2'];
|
1568 |
+
}
|
1569 |
+
return $MPEGaudioBitrate;
|
1570 |
+
}
|
1571 |
+
|
1572 |
+
function MPEGaudioFrequencyArray() {
|
1573 |
+
static $MPEGaudioFrequency;
|
1574 |
+
if (empty($MPEGaudioFrequency)) {
|
1575 |
+
$MPEGaudioFrequency = array (
|
1576 |
+
'1' => array(44100, 48000, 32000),
|
1577 |
+
'2' => array(22050, 24000, 16000),
|
1578 |
+
'2.5' => array(11025, 12000, 8000)
|
1579 |
+
);
|
1580 |
+
}
|
1581 |
+
return $MPEGaudioFrequency;
|
1582 |
+
}
|
1583 |
+
|
1584 |
+
function MPEGaudioChannelModeArray() {
|
1585 |
+
static $MPEGaudioChannelMode = array('stereo', 'joint stereo', 'dual channel', 'mono');
|
1586 |
+
return $MPEGaudioChannelMode;
|
1587 |
+
}
|
1588 |
+
|
1589 |
+
function MPEGaudioModeExtensionArray() {
|
1590 |
+
static $MPEGaudioModeExtension;
|
1591 |
+
if (empty($MPEGaudioModeExtension)) {
|
1592 |
+
$MPEGaudioModeExtension = array (
|
1593 |
+
1 => array('4-31', '8-31', '12-31', '16-31'),
|
1594 |
+
2 => array('4-31', '8-31', '12-31', '16-31'),
|
1595 |
+
3 => array('', 'IS', 'MS', 'IS+MS')
|
1596 |
+
);
|
1597 |
+
}
|
1598 |
+
return $MPEGaudioModeExtension;
|
1599 |
+
}
|
1600 |
+
|
1601 |
+
function MPEGaudioEmphasisArray() {
|
1602 |
+
static $MPEGaudioEmphasis = array('none', '50/15ms', false, 'CCIT J.17');
|
1603 |
+
return $MPEGaudioEmphasis;
|
1604 |
+
}
|
1605 |
+
|
1606 |
+
function MPEGaudioHeaderBytesValid($head4, $allowBitrate15=false) {
|
1607 |
+
return getid3_mp3::MPEGaudioHeaderValid(getid3_mp3::MPEGaudioHeaderDecode($head4), false, $allowBitrate15);
|
1608 |
+
}
|
1609 |
+
|
1610 |
+
function MPEGaudioHeaderValid($rawarray, $echoerrors=false, $allowBitrate15=false) {
|
1611 |
+
if (($rawarray['synch'] & 0x0FFE) != 0x0FFE) {
|
1612 |
+
return false;
|
1613 |
+
}
|
1614 |
+
|
1615 |
+
static $MPEGaudioVersionLookup;
|
1616 |
+
static $MPEGaudioLayerLookup;
|
1617 |
+
static $MPEGaudioBitrateLookup;
|
1618 |
+
static $MPEGaudioFrequencyLookup;
|
1619 |
+
static $MPEGaudioChannelModeLookup;
|
1620 |
+
static $MPEGaudioModeExtensionLookup;
|
1621 |
+
static $MPEGaudioEmphasisLookup;
|
1622 |
+
if (empty($MPEGaudioVersionLookup)) {
|
1623 |
+
$MPEGaudioVersionLookup = getid3_mp3::MPEGaudioVersionArray();
|
1624 |
+
$MPEGaudioLayerLookup = getid3_mp3::MPEGaudioLayerArray();
|
1625 |
+
$MPEGaudioBitrateLookup = getid3_mp3::MPEGaudioBitrateArray();
|
1626 |
+
$MPEGaudioFrequencyLookup = getid3_mp3::MPEGaudioFrequencyArray();
|
1627 |
+
$MPEGaudioChannelModeLookup = getid3_mp3::MPEGaudioChannelModeArray();
|
1628 |
+
$MPEGaudioModeExtensionLookup = getid3_mp3::MPEGaudioModeExtensionArray();
|
1629 |
+
$MPEGaudioEmphasisLookup = getid3_mp3::MPEGaudioEmphasisArray();
|
1630 |
+
}
|
1631 |
+
|
1632 |
+
if (isset($MPEGaudioVersionLookup[$rawarray['version']])) {
|
1633 |
+
$decodedVersion = $MPEGaudioVersionLookup[$rawarray['version']];
|
1634 |
+
} else {
|
1635 |
+
echo ($echoerrors ? "\n".'invalid Version ('.$rawarray['version'].')' : '');
|
1636 |
+
return false;
|
1637 |
+
}
|
1638 |
+
if (isset($MPEGaudioLayerLookup[$rawarray['layer']])) {
|
1639 |
+
$decodedLayer = $MPEGaudioLayerLookup[$rawarray['layer']];
|
1640 |
+
} else {
|
1641 |
+
echo ($echoerrors ? "\n".'invalid Layer ('.$rawarray['layer'].')' : '');
|
1642 |
+
return false;
|
1643 |
+
}
|
1644 |
+
if (!isset($MPEGaudioBitrateLookup[$decodedVersion][$decodedLayer][$rawarray['bitrate']])) {
|
1645 |
+
echo ($echoerrors ? "\n".'invalid Bitrate ('.$rawarray['bitrate'].')' : '');
|
1646 |
+
if ($rawarray['bitrate'] == 15) {
|
1647 |
+
// known issue in LAME 3.90 - 3.93.1 where free-format has bitrate ID of 15 instead of 0
|
1648 |
+
// let it go through here otherwise file will not be identified
|
1649 |
+
if (!$allowBitrate15) {
|
1650 |
+
return false;
|
1651 |
+
}
|
1652 |
+
} else {
|
1653 |
+
return false;
|
1654 |
+
}
|
1655 |
+
}
|
1656 |
+
if (!isset($MPEGaudioFrequencyLookup[$decodedVersion][$rawarray['sample_rate']])) {
|
1657 |
+
echo ($echoerrors ? "\n".'invalid Frequency ('.$rawarray['sample_rate'].')' : '');
|
1658 |
+
return false;
|
1659 |
+
}
|
1660 |
+
if (!isset($MPEGaudioChannelModeLookup[$rawarray['channelmode']])) {
|
1661 |
+
echo ($echoerrors ? "\n".'invalid ChannelMode ('.$rawarray['channelmode'].')' : '');
|
1662 |
+
return false;
|
1663 |
+
}
|
1664 |
+
if (!isset($MPEGaudioModeExtensionLookup[$decodedLayer][$rawarray['modeextension']])) {
|
1665 |
+
echo ($echoerrors ? "\n".'invalid Mode Extension ('.$rawarray['modeextension'].')' : '');
|
1666 |
+
return false;
|
1667 |
+
}
|
1668 |
+
if (!isset($MPEGaudioEmphasisLookup[$rawarray['emphasis']])) {
|
1669 |
+
echo ($echoerrors ? "\n".'invalid Emphasis ('.$rawarray['emphasis'].')' : '');
|
1670 |
+
return false;
|
1671 |
+
}
|
1672 |
+
// These are just either set or not set, you can't mess that up :)
|
1673 |
+
// $rawarray['protection'];
|
1674 |
+
// $rawarray['padding'];
|
1675 |
+
// $rawarray['private'];
|
1676 |
+
// $rawarray['copyright'];
|
1677 |
+
// $rawarray['original'];
|
1678 |
+
|
1679 |
+
return true;
|
1680 |
+
}
|
1681 |
+
|
1682 |
+
function MPEGaudioHeaderDecode($Header4Bytes) {
|
1683 |
+
// AAAA AAAA AAAB BCCD EEEE FFGH IIJJ KLMM
|
1684 |
+
// A - Frame sync (all bits set)
|
1685 |
+
// B - MPEG Audio version ID
|
1686 |
+
// C - Layer description
|
1687 |
+
// D - Protection bit
|
1688 |
+
// E - Bitrate index
|
1689 |
+
// F - Sampling rate frequency index
|
1690 |
+
// G - Padding bit
|
1691 |
+
// H - Private bit
|
1692 |
+
// I - Channel Mode
|
1693 |
+
// J - Mode extension (Only if Joint stereo)
|
1694 |
+
// K - Copyright
|
1695 |
+
// L - Original
|
1696 |
+
// M - Emphasis
|
1697 |
+
|
1698 |
+
if (strlen($Header4Bytes) != 4) {
|
1699 |
+
return false;
|
1700 |
+
}
|
1701 |
+
|
1702 |
+
$MPEGrawHeader['synch'] = (getid3_lib::BigEndian2Int(substr($Header4Bytes, 0, 2)) & 0xFFE0) >> 4;
|
1703 |
+
$MPEGrawHeader['version'] = (ord($Header4Bytes{1}) & 0x18) >> 3; // BB
|
1704 |
+
$MPEGrawHeader['layer'] = (ord($Header4Bytes{1}) & 0x06) >> 1; // CC
|
1705 |
+
$MPEGrawHeader['protection'] = (ord($Header4Bytes{1}) & 0x01); // D
|
1706 |
+
$MPEGrawHeader['bitrate'] = (ord($Header4Bytes{2}) & 0xF0) >> 4; // EEEE
|
1707 |
+
$MPEGrawHeader['sample_rate'] = (ord($Header4Bytes{2}) & 0x0C) >> 2; // FF
|
1708 |
+
$MPEGrawHeader['padding'] = (ord($Header4Bytes{2}) & 0x02) >> 1; // G
|
1709 |
+
$MPEGrawHeader['private'] = (ord($Header4Bytes{2}) & 0x01); // H
|
1710 |
+
$MPEGrawHeader['channelmode'] = (ord($Header4Bytes{3}) & 0xC0) >> 6; // II
|
1711 |
+
$MPEGrawHeader['modeextension'] = (ord($Header4Bytes{3}) & 0x30) >> 4; // JJ
|
1712 |
+
$MPEGrawHeader['copyright'] = (ord($Header4Bytes{3}) & 0x08) >> 3; // K
|
1713 |
+
$MPEGrawHeader['original'] = (ord($Header4Bytes{3}) & 0x04) >> 2; // L
|
1714 |
+
$MPEGrawHeader['emphasis'] = (ord($Header4Bytes{3}) & 0x03); // MM
|
1715 |
+
|
1716 |
+
return $MPEGrawHeader;
|
1717 |
+
}
|
1718 |
+
|
1719 |
+
function MPEGaudioFrameLength(&$bitrate, &$version, &$layer, $padding, &$samplerate) {
|
1720 |
+
static $AudioFrameLengthCache = array();
|
1721 |
+
|
1722 |
+
if (!isset($AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate])) {
|
1723 |
+
$AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate] = false;
|
1724 |
+
if ($bitrate != 'free') {
|
1725 |
+
|
1726 |
+
if ($version == '1') {
|
1727 |
+
|
1728 |
+
if ($layer == '1') {
|
1729 |
+
|
1730 |
+
// For Layer I slot is 32 bits long
|
1731 |
+
$FrameLengthCoefficient = 48;
|
1732 |
+
$SlotLength = 4;
|
1733 |
+
|
1734 |
+
} else { // Layer 2 / 3
|
1735 |
+
|
1736 |
+
// for Layer 2 and Layer 3 slot is 8 bits long.
|
1737 |
+
$FrameLengthCoefficient = 144;
|
1738 |
+
$SlotLength = 1;
|
1739 |
+
|
1740 |
+
}
|
1741 |
+
|
1742 |
+
} else { // MPEG-2 / MPEG-2.5
|
1743 |
+
|
1744 |
+
if ($layer == '1') {
|
1745 |
+
|
1746 |
+
// For Layer I slot is 32 bits long
|
1747 |
+
$FrameLengthCoefficient = 24;
|
1748 |
+
$SlotLength = 4;
|
1749 |
+
|
1750 |
+
} elseif ($layer == '2') {
|
1751 |
+
|
1752 |
+
// for Layer 2 and Layer 3 slot is 8 bits long.
|
1753 |
+
$FrameLengthCoefficient = 144;
|
1754 |
+
$SlotLength = 1;
|
1755 |
+
|
1756 |
+
} else { // layer 3
|
1757 |
+
|
1758 |
+
// for Layer 2 and Layer 3 slot is 8 bits long.
|
1759 |
+
$FrameLengthCoefficient = 72;
|
1760 |
+
$SlotLength = 1;
|
1761 |
+
|
1762 |
+
}
|
1763 |
+
|
1764 |
+
}
|
1765 |
+
|
1766 |
+
// FrameLengthInBytes = ((Coefficient * BitRate) / SampleRate) + Padding
|
1767 |
+
if ($samplerate > 0) {
|
1768 |
+
$NewFramelength = ($FrameLengthCoefficient * $bitrate) / $samplerate;
|
1769 |
+
$NewFramelength = floor($NewFramelength / $SlotLength) * $SlotLength; // round to next-lower multiple of SlotLength (1 byte for Layer 2/3, 4 bytes for Layer I)
|
1770 |
+
if ($padding) {
|
1771 |
+
$NewFramelength += $SlotLength;
|
1772 |
+
}
|
1773 |
+
$AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate] = (int) $NewFramelength;
|
1774 |
+
}
|
1775 |
+
}
|
1776 |
+
}
|
1777 |
+
return $AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate];
|
1778 |
+
}
|
1779 |
+
|
1780 |
+
function ClosestStandardMP3Bitrate($bitrate) {
|
1781 |
+
static $StandardBitrates = array(320000, 256000, 224000, 192000, 160000, 128000, 112000, 96000, 80000, 64000, 56000, 48000, 40000, 32000, 24000, 16000, 8000);
|
1782 |
+
static $BitrateTable = array(0=>'-');
|
1783 |
+
$roundbitrate = intval(round($bitrate, -3));
|
1784 |
+
if (!isset($BitrateTable[$roundbitrate])) {
|
1785 |
+
if ($roundbitrate > 320000) {
|
1786 |
+
$BitrateTable[$roundbitrate] = round($bitrate, -4);
|
1787 |
+
} else {
|
1788 |
+
$LastBitrate = 320000;
|
1789 |
+
foreach ($StandardBitrates as $StandardBitrate) {
|
1790 |
+
$BitrateTable[$roundbitrate] = $StandardBitrate;
|
1791 |
+
if ($roundbitrate >= $StandardBitrate - (($LastBitrate - $StandardBitrate) / 2)) {
|
1792 |
+
break;
|
1793 |
+
}
|
1794 |
+
$LastBitrate = $StandardBitrate;
|
1795 |
+
}
|
1796 |
+
}
|
1797 |
+
}
|
1798 |
+
return $BitrateTable[$roundbitrate];
|
1799 |
+
}
|
1800 |
+
|
1801 |
+
function XingVBRidOffset($version, $channelmode) {
|
1802 |
+
static $XingVBRidOffsetCache = array();
|
1803 |
+
if (empty($XingVBRidOffset)) {
|
1804 |
+
$XingVBRidOffset = array (
|
1805 |
+
'1' => array ('mono' => 0x15, // 4 + 17 = 21
|
1806 |
+
'stereo' => 0x24, // 4 + 32 = 36
|
1807 |
+
'joint stereo' => 0x24,
|
1808 |
+
'dual channel' => 0x24
|
1809 |
+
),
|
1810 |
+
|
1811 |
+
'2' => array ('mono' => 0x0D, // 4 + 9 = 13
|
1812 |
+
'stereo' => 0x15, // 4 + 17 = 21
|
1813 |
+
'joint stereo' => 0x15,
|
1814 |
+
'dual channel' => 0x15
|
1815 |
+
),
|
1816 |
+
|
1817 |
+
'2.5' => array ('mono' => 0x15,
|
1818 |
+
'stereo' => 0x15,
|
1819 |
+
'joint stereo' => 0x15,
|
1820 |
+
'dual channel' => 0x15
|
1821 |
+
)
|
1822 |
+
);
|
1823 |
+
}
|
1824 |
+
return $XingVBRidOffset[$version][$channelmode];
|
1825 |
+
}
|
1826 |
+
|
1827 |
+
function LAMEvbrMethodLookup($VBRmethodID) {
|
1828 |
+
static $LAMEvbrMethodLookup = array(
|
1829 |
+
0x00 => 'unknown',
|
1830 |
+
0x01 => 'cbr',
|
1831 |
+
0x02 => 'abr',
|
1832 |
+
0x03 => 'vbr-old / vbr-rh',
|
1833 |
+
0x04 => 'vbr-new / vbr-mtrh',
|
1834 |
+
0x05 => 'vbr-mt',
|
1835 |
+
0x06 => 'vbr (full vbr method 4)',
|
1836 |
+
0x08 => 'cbr (constant bitrate 2 pass)',
|
1837 |
+
0x09 => 'abr (2 pass)',
|
1838 |
+
0x0F => 'reserved'
|
1839 |
+
);
|
1840 |
+
return (isset($LAMEvbrMethodLookup[$VBRmethodID]) ? $LAMEvbrMethodLookup[$VBRmethodID] : '');
|
1841 |
+
}
|
1842 |
+
|
1843 |
+
function LAMEmiscStereoModeLookup($StereoModeID) {
|
1844 |
+
static $LAMEmiscStereoModeLookup = array(
|
1845 |
+
0 => 'mono',
|
1846 |
+
1 => 'stereo',
|
1847 |
+
2 => 'dual mono',
|
1848 |
+
3 => 'joint stereo',
|
1849 |
+
4 => 'forced stereo',
|
1850 |
+
5 => 'auto',
|
1851 |
+
6 => 'intensity stereo',
|
1852 |
+
7 => 'other'
|
1853 |
+
);
|
1854 |
+
return (isset($LAMEmiscStereoModeLookup[$StereoModeID]) ? $LAMEmiscStereoModeLookup[$StereoModeID] : '');
|
1855 |
+
}
|
1856 |
+
|
1857 |
+
function LAMEmiscSourceSampleFrequencyLookup($SourceSampleFrequencyID) {
|
1858 |
+
static $LAMEmiscSourceSampleFrequencyLookup = array(
|
1859 |
+
0 => '<= 32 kHz',
|
1860 |
+
1 => '44.1 kHz',
|
1861 |
+
2 => '48 kHz',
|
1862 |
+
3 => '> 48kHz'
|
1863 |
+
);
|
1864 |
+
return (isset($LAMEmiscSourceSampleFrequencyLookup[$SourceSampleFrequencyID]) ? $LAMEmiscSourceSampleFrequencyLookup[$SourceSampleFrequencyID] : '');
|
1865 |
+
}
|
1866 |
+
|
1867 |
+
function LAMEsurroundInfoLookup($SurroundInfoID) {
|
1868 |
+
static $LAMEsurroundInfoLookup = array(
|
1869 |
+
0 => 'no surround info',
|
1870 |
+
1 => 'DPL encoding',
|
1871 |
+
2 => 'DPL2 encoding',
|
1872 |
+
3 => 'Ambisonic encoding'
|
1873 |
+
);
|
1874 |
+
return (isset($LAMEsurroundInfoLookup[$SurroundInfoID]) ? $LAMEsurroundInfoLookup[$SurroundInfoID] : 'reserved');
|
1875 |
+
}
|
1876 |
+
|
1877 |
+
function LAMEpresetUsedLookup($LAMEtag) {
|
1878 |
+
|
1879 |
+
if ($LAMEtag['preset_used_id'] == 0) {
|
1880 |
+
// no preset used (LAME >=3.93)
|
1881 |
+
// no preset recorded (LAME <3.93)
|
1882 |
+
return '';
|
1883 |
+
}
|
1884 |
+
$LAMEpresetUsedLookup = array();
|
1885 |
+
|
1886 |
+
///// THIS PART CANNOT BE STATIC .
|
1887 |
+
for ($i = 8; $i <= 320; $i++) {
|
1888 |
+
switch ($LAMEtag['vbr_method']) {
|
1889 |
+
case 'cbr':
|
1890 |
+
$LAMEpresetUsedLookup[$i] = '--alt-preset '.$LAMEtag['vbr_method'].' '.$i;
|
1891 |
+
break;
|
1892 |
+
case 'abr':
|
1893 |
+
default: // other VBR modes shouldn't be here(?)
|
1894 |
+
$LAMEpresetUsedLookup[$i] = '--alt-preset '.$i;
|
1895 |
+
break;
|
1896 |
+
}
|
1897 |
+
}
|
1898 |
+
|
1899 |
+
// named old-style presets (studio, phone, voice, etc) are handled in GuessEncoderOptions()
|
1900 |
+
|
1901 |
+
// named alt-presets
|
1902 |
+
$LAMEpresetUsedLookup[1000] = '--r3mix';
|
1903 |
+
$LAMEpresetUsedLookup[1001] = '--alt-preset standard';
|
1904 |
+
$LAMEpresetUsedLookup[1002] = '--alt-preset extreme';
|
1905 |
+
$LAMEpresetUsedLookup[1003] = '--alt-preset insane';
|
1906 |
+
$LAMEpresetUsedLookup[1004] = '--alt-preset fast standard';
|
1907 |
+
$LAMEpresetUsedLookup[1005] = '--alt-preset fast extreme';
|
1908 |
+
$LAMEpresetUsedLookup[1006] = '--alt-preset medium';
|
1909 |
+
$LAMEpresetUsedLookup[1007] = '--alt-preset fast medium';
|
1910 |
+
|
1911 |
+
// LAME 3.94 additions/changes
|
1912 |
+
$LAMEpresetUsedLookup[1010] = '--preset portable'; // 3.94a15 Oct 21 2003
|
1913 |
+
$LAMEpresetUsedLookup[1015] = '--preset radio'; // 3.94a15 Oct 21 2003
|
1914 |
+
|
1915 |
+
$LAMEpresetUsedLookup[320] = '--preset insane'; // 3.94a15 Nov 12 2003
|
1916 |
+
$LAMEpresetUsedLookup[410] = '-V9';
|
1917 |
+
$LAMEpresetUsedLookup[420] = '-V8';
|
1918 |
+
$LAMEpresetUsedLookup[440] = '-V6';
|
1919 |
+
$LAMEpresetUsedLookup[430] = '--preset radio'; // 3.94a15 Nov 12 2003
|
1920 |
+
$LAMEpresetUsedLookup[450] = '--preset '.(($LAMEtag['raw']['vbr_method'] == 4) ? 'fast ' : '').'portable'; // 3.94a15 Nov 12 2003
|
1921 |
+
$LAMEpresetUsedLookup[460] = '--preset '.(($LAMEtag['raw']['vbr_method'] == 4) ? 'fast ' : '').'medium'; // 3.94a15 Nov 12 2003
|
1922 |
+
$LAMEpresetUsedLookup[470] = '--r3mix'; // 3.94b1 Dec 18 2003
|
1923 |
+
$LAMEpresetUsedLookup[480] = '--preset '.(($LAMEtag['raw']['vbr_method'] == 4) ? 'fast ' : '').'standard'; // 3.94a15 Nov 12 2003
|
1924 |
+
$LAMEpresetUsedLookup[490] = '-V1';
|
1925 |
+
$LAMEpresetUsedLookup[500] = '--preset '.(($LAMEtag['raw']['vbr_method'] == 4) ? 'fast ' : '').'extreme'; // 3.94a15 Nov 12 2003
|
1926 |
+
|
1927 |
+
return (isset($LAMEpresetUsedLookup[$LAMEtag['preset_used_id']]) ? $LAMEpresetUsedLookup[$LAMEtag['preset_used_id']] : 'new/unknown preset: '.$LAMEtag['preset_used_id'].' - report to info@getid3.org');
|
1928 |
+
}
|
1929 |
+
|
1930 |
+
}
|
1931 |
+
|
1932 |
+
?>
|
itunes_default.jpg
ADDED
Binary file
|
mp3info.class.php
ADDED
@@ -0,0 +1,259 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// mp3info class for use in the Blubrry Powerpress
|
3 |
+
// Main purpose of this file is to obtain the duration string for the itunes:duration field.
|
4 |
+
// Library is packaged thin with only basic mp3 support.
|
5 |
+
// Concept with this library is to get the information without downlaoding the entire file.
|
6 |
+
// for efficienccy
|
7 |
+
|
8 |
+
class Mp3Info {
|
9 |
+
//var $m_DownloadBytesLimit = 1638400; // 200K (200*1024*8) bytes file
|
10 |
+
var $m_DownloadBytesLimit = 204800; // 25K (25*1024*8) bytes file
|
11 |
+
var $m_RedirectLimit = 5; // Number of times to do the 302 redirect
|
12 |
+
var $m_UserAgent = 'Blubrry Powerpress/1.0';
|
13 |
+
var $m_error = '';
|
14 |
+
var $m_ContentLength = false;
|
15 |
+
var $m_RedirectCount = 0;
|
16 |
+
|
17 |
+
// Constructor
|
18 |
+
function Mp3Info()
|
19 |
+
{
|
20 |
+
// Empty for now
|
21 |
+
}
|
22 |
+
|
23 |
+
/*
|
24 |
+
Set how much of the media file to download. Default: 25K
|
25 |
+
*/
|
26 |
+
function SetDownloadBytesLimit($limit=204800)
|
27 |
+
{
|
28 |
+
$this->m_DownloadBytesLimit = $limit;
|
29 |
+
}
|
30 |
+
|
31 |
+
/*
|
32 |
+
Set how many times we can follow a HTTP 30x header redirect before we fail.
|
33 |
+
*/
|
34 |
+
function SetRedirectLimit($limit=5)
|
35 |
+
{
|
36 |
+
$this->m_RedirectLimit = $limit;
|
37 |
+
}
|
38 |
+
|
39 |
+
/*
|
40 |
+
Set the user agent to be sent by this plugin
|
41 |
+
*/
|
42 |
+
function SetUserAgent($user_agent)
|
43 |
+
{
|
44 |
+
$this->m_UserAgent = $user_agent;
|
45 |
+
}
|
46 |
+
|
47 |
+
/*
|
48 |
+
Return the last set error message
|
49 |
+
*/
|
50 |
+
function GetError()
|
51 |
+
{
|
52 |
+
return $this->m_error;
|
53 |
+
}
|
54 |
+
|
55 |
+
/*
|
56 |
+
Set the last error message
|
57 |
+
*/
|
58 |
+
function SetError($msg)
|
59 |
+
{
|
60 |
+
$this->m_error = $msg;
|
61 |
+
}
|
62 |
+
|
63 |
+
/*
|
64 |
+
Get the length in bytes of the file to download.
|
65 |
+
*/
|
66 |
+
function GetContentLength()
|
67 |
+
{
|
68 |
+
return $this->m_ContentLength;
|
69 |
+
}
|
70 |
+
|
71 |
+
/*
|
72 |
+
Get the number of times we followed 30x header redirects
|
73 |
+
*/
|
74 |
+
function GetRedirectCount()
|
75 |
+
{
|
76 |
+
return $this->m_RedirectCount;
|
77 |
+
}
|
78 |
+
|
79 |
+
/*
|
80 |
+
Start the download and get the headers, handles the redirect if there are any
|
81 |
+
*/
|
82 |
+
function Download($url, $RedirectCount = 0)
|
83 |
+
{
|
84 |
+
if( $RedirectCount > $this->m_RedirectLimit )
|
85 |
+
{
|
86 |
+
$this->SetError( 'Download exceeded redirect limit of '.$this->m_RedirectLimit .'.' );
|
87 |
+
return false;
|
88 |
+
}
|
89 |
+
|
90 |
+
$this->m_ContentLength = false;
|
91 |
+
$this->m_RedirectCount = $RedirectCount;
|
92 |
+
|
93 |
+
$urlParts = parse_url($url);
|
94 |
+
if( !isset( $urlParts['path']) )
|
95 |
+
$urlParts['path'] = '/';
|
96 |
+
if( !isset( $urlParts['port']) )
|
97 |
+
$urlParts['port'] = 80;
|
98 |
+
if( !isset( $urlParts['scheme']) )
|
99 |
+
$urlParts['scheme'] = 'http';
|
100 |
+
|
101 |
+
$fp = fsockopen($urlParts['host'], $urlParts['port'], $errno, $errstr, 30);
|
102 |
+
if ($fp)
|
103 |
+
{
|
104 |
+
// Create and send the request headers
|
105 |
+
$RequestHeaders = 'GET '.$urlParts['path'].(isset($urlParts['query']) ? '?'.@$urlParts['query'] : '')." HTTP/1.0\r\n";
|
106 |
+
$RequestHeaders .= 'Host: '.$urlParts['host'].($urlParts['port'] != 80 ? ':'.$urlParts['port'] : '')."\r\n";
|
107 |
+
$RequestHeaders .= "Connection: Close\r\n";
|
108 |
+
$RequestHeaders .= "User-Agent: {this->m_UserAgent}\r\n";
|
109 |
+
fwrite($fp, $RequestHeaders."\r\n");
|
110 |
+
|
111 |
+
$Redirect = false;
|
112 |
+
$RedirectURL = false;
|
113 |
+
$ContentLength = false;
|
114 |
+
$ContentType = false;
|
115 |
+
// Loop through the headers
|
116 |
+
while( !feof($fp) )
|
117 |
+
{
|
118 |
+
$line = fgets($fp, 1280); // Get the next header line...
|
119 |
+
if( $line === false )
|
120 |
+
break; // Something happened
|
121 |
+
if ($line == "\r\n")
|
122 |
+
break; // Okay we're ending the headers, now onto the content
|
123 |
+
|
124 |
+
$line = rtrim($line); // Clean out the new line characters
|
125 |
+
|
126 |
+
list($key, $value) = explode(':', $line, 2);
|
127 |
+
$key = trim($key);
|
128 |
+
$value = trim($value);
|
129 |
+
|
130 |
+
if( stristr($line, '301 Moved Permanently') || stristr($line, '302 Found') || stristr($line, '307 Temporary Redirect') )
|
131 |
+
{
|
132 |
+
$Redirect = true; // We are dealing with a redirect, lets handle it
|
133 |
+
}
|
134 |
+
else
|
135 |
+
{
|
136 |
+
switch( strtolower($key) )
|
137 |
+
{
|
138 |
+
case 'location': {
|
139 |
+
$RedirectURL = $value;
|
140 |
+
}; break;
|
141 |
+
case 'content-length': {
|
142 |
+
$ContentLength = $value;
|
143 |
+
}; break;
|
144 |
+
}
|
145 |
+
}
|
146 |
+
}
|
147 |
+
|
148 |
+
// Loop through the content till we reach our limit...
|
149 |
+
$Content = '';
|
150 |
+
if( $this->m_DownloadBytesLimit )
|
151 |
+
{
|
152 |
+
while( !feof($fp) )
|
153 |
+
{
|
154 |
+
$Content .= fread($fp, 8096);
|
155 |
+
if( strlen($Content) > $this->m_DownloadBytesLimit )
|
156 |
+
break; // We got enough of the file we should be able to determine the duration
|
157 |
+
}
|
158 |
+
}
|
159 |
+
fclose($fp);
|
160 |
+
|
161 |
+
// If we're dealing with a redirect, lets call our nested function call now
|
162 |
+
if( $Redirect )
|
163 |
+
{
|
164 |
+
unset($Content); // clear what may be using a lot of memory
|
165 |
+
return $this->Download($RedirectURL, $RedirectCount + 1 ); // Follow this redirect
|
166 |
+
}
|
167 |
+
else // Otherwise, lets set the data and return true for part two
|
168 |
+
{
|
169 |
+
global $TempFile;
|
170 |
+
if( function_exists('get_temp_dir') ) // If wordpress function is available, lets use it
|
171 |
+
$TempFile = tempnam(get_temp_dir(), 'wp_powerpress');
|
172 |
+
else // otherwise use the default path
|
173 |
+
$TempFile = tempnam('/tmp', 'wp_powerpress');
|
174 |
+
|
175 |
+
if( $TempFile === false )
|
176 |
+
{
|
177 |
+
$this->SetError('Unable to save media information to temporary directory.');
|
178 |
+
return false;
|
179 |
+
}
|
180 |
+
|
181 |
+
$fp = fopen( $TempFile, 'w' );
|
182 |
+
fwrite($fp, $Content);
|
183 |
+
fclose($fp);
|
184 |
+
|
185 |
+
if( $ContentLength )
|
186 |
+
$this->m_ContentLength = $ContentLength;
|
187 |
+
return $TempFile;
|
188 |
+
}
|
189 |
+
}
|
190 |
+
$this->SetError('Unable to connect to host '.$urlParts['host'].'.');
|
191 |
+
return false;
|
192 |
+
}
|
193 |
+
|
194 |
+
/*
|
195 |
+
Get the MP3 information
|
196 |
+
*/
|
197 |
+
function GetMp3Info($File)
|
198 |
+
{
|
199 |
+
$DeleteFile = false;
|
200 |
+
if( strtolower( substr($File, 0, 7) ) == 'http://' )
|
201 |
+
{
|
202 |
+
$LocalFile = $this->Download($File);
|
203 |
+
if( $LocalFile === false )
|
204 |
+
return false;
|
205 |
+
$DeleteFile = true;
|
206 |
+
}
|
207 |
+
else
|
208 |
+
{
|
209 |
+
$LocalFile = $File;
|
210 |
+
}
|
211 |
+
|
212 |
+
// Hack so this works in Windows, helper apps are not necessary for what we're doing anyway
|
213 |
+
define('GETID3_HELPERAPPSDIR', true);
|
214 |
+
require_once(dirname(__FILE__).'/getid3/getid3.php');
|
215 |
+
$getID3 = new getID3;
|
216 |
+
$FileInfo = $getID3->analyze( $LocalFile, $this->m_ContentLength );
|
217 |
+
if( $DeleteFile )
|
218 |
+
@unlink($LocalFile);
|
219 |
+
|
220 |
+
if( $FileInfo )
|
221 |
+
{
|
222 |
+
// Remove extra data that is not necessary for us to return...
|
223 |
+
unset($FileInfo['mpeg']);
|
224 |
+
unset($FileInfo['audio']);
|
225 |
+
if( isset($FileInfo['id3v2']) )
|
226 |
+
unset($FileInfo['id3v2']);
|
227 |
+
if( isset($FileInfo['id3v1']) )
|
228 |
+
unset($FileInfo['id3v1']);
|
229 |
+
|
230 |
+
$FileInfo['playtime_seconds'] = round($FileInfo['playtime_seconds']);
|
231 |
+
return $FileInfo;
|
232 |
+
}
|
233 |
+
|
234 |
+
return false;
|
235 |
+
}
|
236 |
+
};
|
237 |
+
|
238 |
+
/*
|
239 |
+
// Example usage:
|
240 |
+
|
241 |
+
$Mp3Info = new Mp3Info();
|
242 |
+
if( $Data = $Mp3Info->GetMp3Info('http://www.podcampohio.com/podpress_trac/web/177/0/TS-107667.mp3') )
|
243 |
+
{
|
244 |
+
echo 'Success: ';
|
245 |
+
echo print_r( $Data );
|
246 |
+
echo PHP_EOL;
|
247 |
+
exit;
|
248 |
+
}
|
249 |
+
else
|
250 |
+
{
|
251 |
+
echo 'Error: ';
|
252 |
+
echo $Mp3Info->GetError();
|
253 |
+
echo PHP_EOL;
|
254 |
+
exit;
|
255 |
+
}
|
256 |
+
*/
|
257 |
+
|
258 |
+
|
259 |
+
?>
|
player.js
ADDED
@@ -0,0 +1,373 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* jsMediaPlayer 1.0 for Blubrry Powerpress
|
3 |
+
*
|
4 |
+
* http://www.blubrry.com/powepress/
|
5 |
+
*
|
6 |
+
* Copyright (c) 2008 Angelo Mandato (angelo [at] mandato {period} com)
|
7 |
+
*
|
8 |
+
* Released under Aoache 2 license:
|
9 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10 |
+
*
|
11 |
+
* version 1.0.2 - 07/26/2008 - Fixed pop up player bug caused by v 1.0.1
|
12 |
+
* version 1.0.1 - 07/28/2008 - fixed flow player looping playback, flash player no longer loops.
|
13 |
+
* version 1.0.0 - 07/26/2008 - initial release
|
14 |
+
*/
|
15 |
+
|
16 |
+
function jsMediaPlayer(FlashSrc) {
|
17 |
+
// Member variables
|
18 |
+
this.m_flash_src = FlashSrc;
|
19 |
+
this.m_auto_play = false;
|
20 |
+
this.m_width = 320;
|
21 |
+
this.m_height = 240;
|
22 |
+
this.m_player_div = false;
|
23 |
+
this.m_player_wnd = false;
|
24 |
+
this.m_one_player_only = false;
|
25 |
+
this.m_media_url = false;
|
26 |
+
|
27 |
+
|
28 |
+
this.FlashSrc=function(Src) {
|
29 |
+
this.m_flash_src = Src;
|
30 |
+
}
|
31 |
+
|
32 |
+
this.AutoPlay=function(Setting) {
|
33 |
+
this.m_auto_play = Setting;
|
34 |
+
}
|
35 |
+
|
36 |
+
this.SetWidth=function(Width) {
|
37 |
+
this.m_width = Width;
|
38 |
+
}
|
39 |
+
|
40 |
+
this.SetHeight=function(Height) {
|
41 |
+
this.m_height = Height;
|
42 |
+
}
|
43 |
+
|
44 |
+
this.OnePlayerOnly=function(Setting) {
|
45 |
+
this.m_one_player_only = Setting;
|
46 |
+
}
|
47 |
+
|
48 |
+
this.PlayInPage = function() {
|
49 |
+
|
50 |
+
// Check if we should even use javascript based player
|
51 |
+
if( this._passthru() )
|
52 |
+
return true;
|
53 |
+
|
54 |
+
// Make sure we're not already playing this div...
|
55 |
+
if( this.m_player_div == this.PlayInPage.arguments[1] )
|
56 |
+
return false;
|
57 |
+
|
58 |
+
// Close the last opened player
|
59 |
+
if( this.m_one_player_only )
|
60 |
+
this._closePrevPlayer();
|
61 |
+
|
62 |
+
// Set the proeprties:
|
63 |
+
this.m_media_url = this.PlayInPage.arguments[0];
|
64 |
+
this.m_player_div = this.PlayInPage.arguments[1];
|
65 |
+
|
66 |
+
var ext = this._getExt(this.m_media_url);
|
67 |
+
switch( ext )
|
68 |
+
{
|
69 |
+
case 'm4v':
|
70 |
+
case 'm4a':
|
71 |
+
case 'avi':
|
72 |
+
case 'mpg':
|
73 |
+
case 'mpeg':
|
74 |
+
case 'mp4':
|
75 |
+
case 'qt':
|
76 |
+
case 'mov': {
|
77 |
+
|
78 |
+
var contentType = 'video/mpeg'; // Default content type
|
79 |
+
if( ext == 'm4v' )
|
80 |
+
contentType = 'video/x-m4v';
|
81 |
+
else if( ext == 'm4a' )
|
82 |
+
contentType = 'audio/x-m4a';
|
83 |
+
else if( ext == 'avi' )
|
84 |
+
contentType = 'video/avi';
|
85 |
+
else if( ext == 'qt' || ext == 'mov' )
|
86 |
+
contentType = 'video/quicktime';
|
87 |
+
|
88 |
+
document.getElementById( this.m_player_div ).innerHTML = this._getQuickTime(contentType);
|
89 |
+
}; break;
|
90 |
+
case 'wma':
|
91 |
+
case 'wmv':
|
92 |
+
case 'asf': {
|
93 |
+
document.getElementById( this.m_player_div ).innerHTML = this._getWinPlayer();
|
94 |
+
}; break;
|
95 |
+
case 'rm': {
|
96 |
+
document.getElementById( this.m_player_div ).innerHTML = this._getRealPlayer();
|
97 |
+
}
|
98 |
+
case 'swf': {
|
99 |
+
document.getElementById( this.m_player_div ).innerHTML = this._getFlash();
|
100 |
+
}
|
101 |
+
case 'flv': {
|
102 |
+
this._doFlowPlayer();
|
103 |
+
}; break;
|
104 |
+
case 'mp3': {
|
105 |
+
this._doFlowPlayer(24);
|
106 |
+
|
107 |
+
}; break;
|
108 |
+
default: {
|
109 |
+
return true; // We didn't handle this, so lets let the click to the media handle itself.
|
110 |
+
};
|
111 |
+
}
|
112 |
+
|
113 |
+
// Display the div
|
114 |
+
document.getElementById( this.m_player_div ).style.display = 'block';
|
115 |
+
return false; // Don't let the href go
|
116 |
+
}
|
117 |
+
|
118 |
+
this.PlayNewWindow=function() {
|
119 |
+
|
120 |
+
// Check if we should even use javascript based player
|
121 |
+
if( this._passthru() )
|
122 |
+
return true;
|
123 |
+
|
124 |
+
if( this.m_one_player_only )
|
125 |
+
this._closePrevPlayer();
|
126 |
+
|
127 |
+
// Get the media file and extension
|
128 |
+
this.m_media_url = this.PlayNewWindow.arguments[0];
|
129 |
+
var ext = this._getExt(this.m_media_url);
|
130 |
+
|
131 |
+
// Calculate the window height
|
132 |
+
height = this.m_height;
|
133 |
+
if( ext == 'mp3' )
|
134 |
+
{
|
135 |
+
height = 24;
|
136 |
+
// Adjust the height for Opera web browser, only needed for mp3s
|
137 |
+
if( navigator.userAgent.indexOf("Opera") != -1 )
|
138 |
+
height += 40;
|
139 |
+
}
|
140 |
+
else
|
141 |
+
height += 40; // Add area for menu navigation
|
142 |
+
|
143 |
+
this.m_player_wnd = window.open(null,"jsPlayer", 'toolbar=0,status=0,resizable=1,width='+ (this.m_width +40).toString() +',height='+ height.toString() )
|
144 |
+
var Html = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
|
145 |
+
Html += '<html xmlns="http://www.w3.org/1999/xhtml">';
|
146 |
+
Html += '<head>';
|
147 |
+
Html += '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
|
148 |
+
Html += '<title>Media Player</title>';
|
149 |
+
if( ext == 'mp3' || ext == 'flv' || ext == 'mp4' )
|
150 |
+
{
|
151 |
+
Html += '<script type="text/javascript">\n';
|
152 |
+
Html += 'function flashembed(root,userParams,flashvars){function getHTML(){var html="";if(typeof flashvars==\'function\'){flashvars=flashvars();}if(navigator.plugins&&navigator.mimeTypes&&navigator.mimeTypes.length){html=\'<embed type="application/x-shockwave-flash" \';if(params.id){extend(params,{name:params.id});}for(var key in params){if(params[key]!==null){html+=[key]+\'="\'+params[key]+\'"\\n\\t\';}}if(flashvars){html+=\'flashvars=\\\'\'+concatVars(flashvars)+\'\\\'\';}html+=\'/>\';}else{html=\'<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" \';html+=\'width="\'+params.width+\'" height="\'+params.height+\'"\';if(!params.id&&document.all){params.id="_"+(""+Math.random()).substring(5);}if(params.id){html+=\' id="\'+params.id+\'"\';}html+=\'>\';html+=\'\\n\\t<param name="movie" value="\'+params.src+\'" />\';params.id=params.src=params.width=params.height=null;for(var k in params){if(params[k]!==null){html+=\'\\n\\t<param name="\'+k+\'" value="\'+params[k]+\'" />\';}}if(flashvars){html+=\'\\n\\t<param name="flashvars" value=\\\'\'+concatVars(flashvars)+\'\\\' />\';}html+="</object>";if(debug){alert(html);}}return html;}function init(name){var timer=setInterval(function(){var doc=document;var el=doc.getElementById(name);if(el){flashembed(el,userParams,flashvars);clearInterval(timer);}else if(doc&&doc.getElementsByTagName&&doc.getElementById&&doc.body){clearInterval(timer);}},13);return true;}function extend(to,from){if(from){for(key in from){if(from.hasOwnProperty(key)){to[key]=from[key];}}}}var params={src:\'#\',width:\'100%\',height:\'100%\',version:null,onFail:null,expressInstall:null,debug:false,bgcolor:\'#ffffff\',allowfullscreen:true,allowscriptaccess:\'always\',quality:\'high\',type:\'application/x-shockwave-flash\',pluginspage:\'http://www.adobe.com/go/getflashplayer\'};if(typeof userParams==\'string\'){userParams={src:userParams};}extend(params,userParams);var version=flashembed.getVersion();var required=params.version;var express=params.expressInstall;var debug=params.debug;if(typeof root==\'string\'){var el=document.getElementById(root);if(el){root=el;}else{return init(root);}}if(!root){return;}if(!required||flashembed.isSupported(required)){params.onFail=params.version=params.expressInstall=params.debug=null;root.innerHTML=getHTML();return root.firstChild;}else if(params.onFail){var ret=params.onFail.call(params,flashembed.getVersion(),flashvars);if(ret){root.innerHTML=ret;}}else if(required&&express&&flashembed.isSupported([6,65])){extend(params,{src:express});flashvars={MMredirectURL:location.href,MMplayerType:\'PlugIn\',MMdoctitle:document.title};root.innerHTML=getHTML();}else{if(root.innerHTML.replace(/\\s/g,\'\')!==\'\'){}else{root.innerHTML="<h2>Flash version "+required+" or greater is required</h2>"+"<h3>"+(version[0]>0?"Your version is "+version:"You have no flash plugin installed")+"</h3>"+"<p>Download latest version from <a href=\'"+params.pluginspage+"\'>here</a></p>";}}function concatVars(vars){var out="";for(var key in vars){if(vars[key]){out+=[key]+\'=\'+asString(vars[key])+\'&\';}}return out.substring(0,out.length-1);}function asString(obj){switch(typeOf(obj)){case\'string\':return\'"\'+obj.replace(new RegExp(\'(["\\\\\\\\])\',\'g\'),\'\\\\$1\')+\'"\';case\'array\':return\'[\'+map(obj,function(el){return asString(el);}).join(\',\')+\']\';case\'function\':return\'"function()"\';case\'object\':var str=[];for(var prop in obj){if(obj.hasOwnProperty(prop)){str.push(\'"\'+prop+\'":\'+asString(obj[prop]));}}return\'{\'+str.join(\',\')+\'}\';}return String(obj).replace(/\\s/g," ").replace(/\\\'/g,"\\"");}function typeOf(obj){if(obj===null||obj===undefined){return false;}var type=typeof obj;return(type==\'object\'&&obj.push)?\'array\':type;}if(window.attachEvent){window.attachEvent("onbeforeunload",function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};});}function map(arr,func){var newArr=[];for(var i in arr){if(arr.hasOwnProperty(i)){newArr[i]=func(arr[i]);}}return newArr;}return root;}if(typeof jQuery==\'function\'){(function($){$.fn.extend({flashembed:function(params,flashvars){return this.each(function(){flashembed(this,params,flashvars);});}});})(jQuery);}flashembed=flashembed||{};flashembed.getVersion=function(){var version=[0,0];if(navigator.plugins&&typeof navigator.plugins["Shockwave Flash"]=="object"){var _d=navigator.plugins["Shockwave Flash"].description;if(typeof _d!="undefined"){_d=_d.replace(/^.*\\s+(\\S+\\s+\\S+$)/,"$1");var _m=parseInt(_d.replace(/^(.*)\\..*$/,"$1"),10);var _r=/r/.test(_d)?parseInt(_d.replace(/^.*r(.*)$/,"$1"),10):0;version=[_m,_r];}}else if(window.ActiveXObject){try{var _a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");}catch(e){try{_a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");version=[6,0];_a.AllowScriptAccess="always";}catch(ee){if(version[0]==6){return;}}try{_a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");}catch(eee){}}if(typeof _a=="object"){_d=_a.GetVariable("$version");if(typeof _d!="undefined"){_d=_d.replace(/^\\S+\\s+(.*)$/,"$1").split(",");version=[parseInt(_d[0],10),parseInt(_d[2],10)];}}}return version;};flashembed.isSupported=function(version){var now=flashembed.getVersion();var ret=(now[0]>version[0])||(now[0]==version[0]&&now[1]>=version[1]);return ret;};\n';
|
153 |
+
Html += '</script>\n';
|
154 |
+
}
|
155 |
+
Html += '</head>';
|
156 |
+
Html += '<body>';
|
157 |
+
Html += '<div id="player" style="margin-top: 20px; margin-left: 10px;">';
|
158 |
+
if( ext != 'mp3' && ext != 'flv' && ext != 'mp4' )
|
159 |
+
{
|
160 |
+
switch( ext )
|
161 |
+
{
|
162 |
+
case 'm4v':
|
163 |
+
case 'm4a':
|
164 |
+
case 'avi':
|
165 |
+
case 'mpg':
|
166 |
+
case 'mpeg':
|
167 |
+
case 'qt':
|
168 |
+
case 'mov': {
|
169 |
+
|
170 |
+
var contentType = 'video/mpeg'; // Default content type
|
171 |
+
if( ext == 'm4v' )
|
172 |
+
contentType = 'video/x-m4v';
|
173 |
+
else if( ext == 'm4a' )
|
174 |
+
contentType = 'audio/x-m4a';
|
175 |
+
else if( ext == 'avi' )
|
176 |
+
contentType = 'video/avi';
|
177 |
+
else if( ext == 'qt' || ext == 'mov' )
|
178 |
+
contentType = 'video/quicktime';
|
179 |
+
|
180 |
+
Html += this._getQuickTime(contentType);
|
181 |
+
}; break;
|
182 |
+
case 'wma':
|
183 |
+
case 'wmv':
|
184 |
+
case 'asf': {
|
185 |
+
Html += this._getWinPlayer();
|
186 |
+
}; break;
|
187 |
+
case 'rm': {
|
188 |
+
Html += this._getRealPlayer();
|
189 |
+
}; break;
|
190 |
+
case 'swf': {
|
191 |
+
Html += this._getFlash();
|
192 |
+
}; break;
|
193 |
+
}
|
194 |
+
}
|
195 |
+
Html += '</div>';
|
196 |
+
if( ext == 'mp3' || ext == 'flv' || ext == 'mp4' )
|
197 |
+
{
|
198 |
+
Html += '<script type="text/javascript">\n';
|
199 |
+
if( ext == 'mp3' )
|
200 |
+
Html += this._getFlowPlayer('player', 24, true);
|
201 |
+
else
|
202 |
+
Html += this._getFlowPlayer('player', this.m_height, true);
|
203 |
+
Html += '</script>\n';
|
204 |
+
}
|
205 |
+
Html += '</body>';
|
206 |
+
Html += '</html>';
|
207 |
+
this.m_player_wnd.document.write( Html );
|
208 |
+
this.m_player_wnd.document.close();
|
209 |
+
this.m_player_wnd.focus();
|
210 |
+
return false;
|
211 |
+
}
|
212 |
+
|
213 |
+
/*
|
214 |
+
Private functions:
|
215 |
+
*/
|
216 |
+
this._doFlowPlayer = function() {
|
217 |
+
|
218 |
+
var height = this.m_height;
|
219 |
+
if( this._doFlowPlayer.arguments.length > 0 )
|
220 |
+
height = this._doFlowPlayer.arguments[0];
|
221 |
+
|
222 |
+
flashembed(
|
223 |
+
this.m_player_div,
|
224 |
+
{src: this.m_flash_src, width: this.m_width, height: height },
|
225 |
+
{config: { autoPlay: this.m_auto_play?true:false, autoBuffering: false, initialScale: 'scale', showFullScreenButton: false, showMenu: false, videoFile: this.m_media_url, loop: false, autoRewind: true } }
|
226 |
+
);
|
227 |
+
|
228 |
+
return false;
|
229 |
+
}
|
230 |
+
|
231 |
+
this._getFlowPlayer = function(destDiv) {
|
232 |
+
|
233 |
+
var height = this.m_height;
|
234 |
+
if( this._getFlowPlayer.arguments.length > 1 )
|
235 |
+
height = this._getFlowPlayer.arguments[1];
|
236 |
+
|
237 |
+
var auto_play = this.m_auto_play;
|
238 |
+
if( this._getFlowPlayer.arguments.length > 2 )
|
239 |
+
auto_play = this._getFlowPlayer.arguments[2];
|
240 |
+
|
241 |
+
var Html = '';
|
242 |
+
Html += "flashembed(\n";
|
243 |
+
Html += " '"+ destDiv +"', \n";
|
244 |
+
Html += " {src: '"+ this.m_flash_src +"', width: "+ this.m_width +", height: "+ height +"}, \n";
|
245 |
+
Html += " {config: { autoPlay: "+ (auto_play?'true':'false') +", autoBuffering: false, initialScale: 'scale', showFullScreenButton: false, showMenu: false, videoFile: '"+ this.m_media_url +"', loop: false, autoRewind: true } } \n";
|
246 |
+
Html += " ); \n";
|
247 |
+
return Html;
|
248 |
+
}
|
249 |
+
|
250 |
+
this._getFlash = function() {
|
251 |
+
|
252 |
+
var Html = '';
|
253 |
+
Html += '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0"'+ (this.m_auto_play?'':' play="false"') +' width="'+ this.m_width +'" height="'+ this.m_height +'" menu="true">\n';
|
254 |
+
Html += ' <param name="movie" value="'+ this.m_media_url +'" />\n';
|
255 |
+
Html += ' <param name="quality" value="high" />\n';
|
256 |
+
Html += ' <param name="menu" value="true" />\n';
|
257 |
+
Html += ' <param name="scale" value="noorder" />\n';
|
258 |
+
Html += ' <param name="quality" value="high" />\n';
|
259 |
+
Html += ' <embed src="'+ this.m_media_url +'" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash"'+ (this.m_auto_play?'':' play="false"') +' width="'+ this.m_width +'" height="'+ this.m_height +'" menu="true"></embed>';
|
260 |
+
Html += '</object>\n';
|
261 |
+
return Html;
|
262 |
+
}
|
263 |
+
|
264 |
+
this._getRealPlayer = function() {
|
265 |
+
|
266 |
+
var Html = '';
|
267 |
+
Html += '<object id="realplayer" classid="clsid:cfcdaa03-8be4-11cf-b84b-0020afbbccfa" width="'+ this.m_width +'" height="'+ this.m_height +'">\n';
|
268 |
+
Html += ' <param name="src" value="'+ this.m_media_url +'" />\n';
|
269 |
+
Html += ' <param name="autostart" value="'+ (this.m_auto_play?'true':'false') +'" />\n';
|
270 |
+
Html += ' <param name="controls" value="imagewindow,controlpanel" />\n';
|
271 |
+
Html += ' <embed src="'+ this.m_media_url +'" width="'+ this.m_width +'" height="'+ this.m_height +'" autostart="'+(this.m_auto_play?'true':'false')+'" controls="imagewindow,controlpanel" type="audio/x-pn-realaudio-plugin"></embed>';
|
272 |
+
Html += '</object>\n';
|
273 |
+
return Html;
|
274 |
+
}
|
275 |
+
|
276 |
+
this._getWinPlayer = function() {
|
277 |
+
|
278 |
+
var Html = '';
|
279 |
+
Html += '<object id="winplayer" classid="clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6" width="'+ this.m_width +'" height="'+ this.m_height +'" standby="Media is loading..." type="application/x-oleobject">\n';
|
280 |
+
Html += ' <param name="url" value="'+ this.m_media_url +'" />\n';
|
281 |
+
Html += ' <param name="AutoStart" value="'+ (this.m_auto_play?'true':'false') +'" />\n';
|
282 |
+
Html += ' <param name="AutoSize" value="true" />\n';
|
283 |
+
Html += ' <param name="AllowChangeDisplaySize" value="true" />\n';
|
284 |
+
Html += ' <param name="standby" value="Media is loading..." />\n';
|
285 |
+
Html += ' <param name="AnimationAtStart" value="true" />\n';
|
286 |
+
Html += ' <param name="scale" value="aspect" />\n';
|
287 |
+
Html += ' <param name="ShowControls" value="true" />\n';
|
288 |
+
Html += ' <param name="ShowCaptioning" value="false" />\n';
|
289 |
+
Html += ' <param name="ShowDisplay" value="false" />\n';
|
290 |
+
Html += ' <param name="ShowStatusBar" value="false" />\n';
|
291 |
+
Html += ' <embed type="application/x-mplayer2" src="'+ this.m_media_url +'" width="'+ this.m_width +'" height="'+ this.m_height +'" scale="aspect" AutoStart="'+ (this.m_auto_play?'true':'false') +'" ShowDisplay="0" ShowStatusBar="0" AutoSize="1" AnimationAtStart="1" AllowChangeDisplaySize="1" ShowControls="1"></embed>\n';
|
292 |
+
Html += '</object>\n';
|
293 |
+
return Html;
|
294 |
+
}
|
295 |
+
|
296 |
+
this._getQuickTime = function() {
|
297 |
+
|
298 |
+
var contentType = 'video/mpeg';
|
299 |
+
if( this._getQuickTime.arguments.length > 0 )
|
300 |
+
contentType = this._getQuickTime.arguments[0];
|
301 |
+
|
302 |
+
var Html = '';
|
303 |
+
Html += '<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" width="'+ this.m_width +'" height="'+ this.m_height +'" codebase="http://www.apple.com/qtactivex/qtplugin.cab">\n';
|
304 |
+
Html += ' <param name="src" value="'+ this.m_media_url +'" />\n';
|
305 |
+
Html += ' <param name="href" value="'+ this.m_media_url +'" />\n';
|
306 |
+
Html += ' <param name="scale" value="aspect" />\n';
|
307 |
+
Html += ' <param name="controller" value="true" />\n';
|
308 |
+
Html += ' <param name="autoplay" value="'+ (this.m_auto_play?'true':'false') +'" />\n';
|
309 |
+
Html += ' <param name="bgcolor" value="000000" />\n';
|
310 |
+
Html += ' <param name="pluginspage" value="http://www.apple.com/quicktime/download/" />\n';
|
311 |
+
Html += ' <embed src="'+ this.m_media_url +'" type="'+ contentType +'" width="'+ this.m_width +'" height="'+ this.m_height +'" scale="aspect" cache="true" bgcolor="000000" autoplay="'+ (this.m_auto_play?'true':'false') +'" controller="true" pluginspage="http://www.apple.com/quicktime/download/"></embed>';
|
312 |
+
Html += '</object>\n';
|
313 |
+
return Html;
|
314 |
+
}
|
315 |
+
|
316 |
+
this._getExt = function(File) {
|
317 |
+
// First remove any anchor if any
|
318 |
+
var anchor = File.indexOf('#');
|
319 |
+
if( anchor > -1 )
|
320 |
+
File = File.substring(0, anchor);
|
321 |
+
// Next, get rid of the query string if exists..
|
322 |
+
var question = File.indexOf('?');
|
323 |
+
if( question > -1 )
|
324 |
+
File = File.substring(0, question);
|
325 |
+
// Find the last dot at the end of the file
|
326 |
+
var dot = File.lastIndexOf('.');
|
327 |
+
if( dot > -1 )
|
328 |
+
return File.substring(dot+1).toLowerCase();
|
329 |
+
return false; // Unable to find a file extension
|
330 |
+
}
|
331 |
+
|
332 |
+
this._passthru = function() {
|
333 |
+
|
334 |
+
// If we have ourselves an iPhone, let the media passtru when clicked
|
335 |
+
if( navigator.userAgent.indexOf("iPhone") != -1 )
|
336 |
+
return true; // Let this client download and play the content itself.
|
337 |
+
|
338 |
+
// Add additional user agents which cannot handle embed, object or flash code here:
|
339 |
+
|
340 |
+
return false;
|
341 |
+
}
|
342 |
+
|
343 |
+
this._closePrevPlayer = function() {
|
344 |
+
if( this.m_player_div )
|
345 |
+
{
|
346 |
+
document.getElementById( this.m_player_div ).innerHTML = '';
|
347 |
+
document.getElementById( this.m_player_div ).style.display = 'none';
|
348 |
+
this.m_player_div = false;
|
349 |
+
}
|
350 |
+
if( this.m_player_wnd )
|
351 |
+
{
|
352 |
+
this.m_player_wnd.close();
|
353 |
+
this.m_player_wnd = false;
|
354 |
+
}
|
355 |
+
}
|
356 |
+
}
|
357 |
+
|
358 |
+
/**
|
359 |
+
* flashembed 0.31. Adobe Flash embedding script
|
360 |
+
*
|
361 |
+
* http://flowplayer.org/tools/flash-embed.html
|
362 |
+
*
|
363 |
+
* Copyright (c) 2008 Tero Piirainen (tipiirai@gmail.com)
|
364 |
+
*
|
365 |
+
* Released under the MIT License:
|
366 |
+
* http://www.opensource.org/licenses/mit-license.php
|
367 |
+
*
|
368 |
+
* >> Basically you can do anything you want but leave this header as is <<
|
369 |
+
*
|
370 |
+
* version 0.01 - 03/11/2008
|
371 |
+
* version 0.31 - Tue Jul 22 2008 06:30:31 GMT+0200 (GMT+02:00)
|
372 |
+
*/
|
373 |
+
function flashembed(root,userParams,flashvars){function getHTML(){var html="";if(typeof flashvars=='function'){flashvars=flashvars();}if(navigator.plugins&&navigator.mimeTypes&&navigator.mimeTypes.length){html='<embed type="application/x-shockwave-flash" ';if(params.id){extend(params,{name:params.id});}for(var key in params){if(params[key]!==null){html+=[key]+'="'+params[key]+'"\n\t';}}if(flashvars){html+='flashvars=\''+concatVars(flashvars)+'\'';}html+='/>';}else{html='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" ';html+='width="'+params.width+'" height="'+params.height+'"';if(!params.id&&document.all){params.id="_"+(""+Math.random()).substring(5);}if(params.id){html+=' id="'+params.id+'"';}html+='>';html+='\n\t<param name="movie" value="'+params.src+'" />';params.id=params.src=params.width=params.height=null;for(var k in params){if(params[k]!==null){html+='\n\t<param name="'+k+'" value="'+params[k]+'" />';}}if(flashvars){html+='\n\t<param name="flashvars" value=\''+concatVars(flashvars)+'\' />';}html+="</object>";if(debug){alert(html);}}return html;}function init(name){var timer=setInterval(function(){var doc=document;var el=doc.getElementById(name);if(el){flashembed(el,userParams,flashvars);clearInterval(timer);}else if(doc&&doc.getElementsByTagName&&doc.getElementById&&doc.body){clearInterval(timer);}},13);return true;}function extend(to,from){if(from){for(key in from){if(from.hasOwnProperty(key)){to[key]=from[key];}}}}var params={src:'#',width:'100%',height:'100%',version:null,onFail:null,expressInstall:null,debug:false,bgcolor:'#ffffff',allowfullscreen:true,allowscriptaccess:'always',quality:'high',type:'application/x-shockwave-flash',pluginspage:'http://www.adobe.com/go/getflashplayer'};if(typeof userParams=='string'){userParams={src:userParams};}extend(params,userParams);var version=flashembed.getVersion();var required=params.version;var express=params.expressInstall;var debug=params.debug;if(typeof root=='string'){var el=document.getElementById(root);if(el){root=el;}else{return init(root);}}if(!root){return;}if(!required||flashembed.isSupported(required)){params.onFail=params.version=params.expressInstall=params.debug=null;root.innerHTML=getHTML();return root.firstChild;}else if(params.onFail){var ret=params.onFail.call(params,flashembed.getVersion(),flashvars);if(ret){root.innerHTML=ret;}}else if(required&&express&&flashembed.isSupported([6,65])){extend(params,{src:express});flashvars={MMredirectURL:location.href,MMplayerType:'PlugIn',MMdoctitle:document.title};root.innerHTML=getHTML();}else{if(root.innerHTML.replace(/\s/g,'')!==''){}else{root.innerHTML="<h2>Flash version "+required+" or greater is required</h2>"+"<h3>"+(version[0]>0?"Your version is "+version:"You have no flash plugin installed")+"</h3>"+"<p>Download latest version from <a href='"+params.pluginspage+"'>here</a></p>";}}function concatVars(vars){var out="";for(var key in vars){if(vars[key]){out+=[key]+'='+asString(vars[key])+'&';}}return out.substring(0,out.length-1);}function asString(obj){switch(typeOf(obj)){case'string':return'"'+obj.replace(new RegExp('(["\\\\])','g'),'\\$1')+'"';case'array':return'['+map(obj,function(el){return asString(el);}).join(',')+']';case'function':return'"function()"';case'object':var str=[];for(var prop in obj){if(obj.hasOwnProperty(prop)){str.push('"'+prop+'":'+asString(obj[prop]));}}return'{'+str.join(',')+'}';}return String(obj).replace(/\s/g," ").replace(/\'/g,"\"");}function typeOf(obj){if(obj===null||obj===undefined){return false;}var type=typeof obj;return(type=='object'&&obj.push)?'array':type;}if(window.attachEvent){window.attachEvent("onbeforeunload",function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};});}function map(arr,func){var newArr=[];for(var i in arr){if(arr.hasOwnProperty(i)){newArr[i]=func(arr[i]);}}return newArr;}return root;}if(typeof jQuery=='function'){(function($){$.fn.extend({flashembed:function(params,flashvars){return this.each(function(){flashembed(this,params,flashvars);});}});})(jQuery);}flashembed=flashembed||{};flashembed.getVersion=function(){var version=[0,0];if(navigator.plugins&&typeof navigator.plugins["Shockwave Flash"]=="object"){var _d=navigator.plugins["Shockwave Flash"].description;if(typeof _d!="undefined"){_d=_d.replace(/^.*\s+(\S+\s+\S+$)/,"$1");var _m=parseInt(_d.replace(/^(.*)\..*$/,"$1"),10);var _r=/r/.test(_d)?parseInt(_d.replace(/^.*r(.*)$/,"$1"),10):0;version=[_m,_r];}}else if(window.ActiveXObject){try{var _a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");}catch(e){try{_a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");version=[6,0];_a.AllowScriptAccess="always";}catch(ee){if(version[0]==6){return;}}try{_a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");}catch(eee){}}if(typeof _a=="object"){_d=_a.GetVariable("$version");if(typeof _d!="undefined"){_d=_d.replace(/^\S+\s+(.*)$/,"$1").split(",");version=[parseInt(_d[0],10),parseInt(_d[2],10)];}}}return version;};flashembed.isSupported=function(version){var now=flashembed.getVersion();var ret=(now[0]>version[0])||(now[0]==version[0]&&now[1]>=version[1]);return ret;};
|
powerpress.php
ADDED
@@ -0,0 +1,655 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
Plugin Name: Blubrry Powerpress
|
4 |
+
Plugin URI: http://www.blubrry.com/powerpress/
|
5 |
+
Description: <a href="http://www.blubrry.com/powerpress/" target="_blank">Blubrry Powerpress</a> adds podcasting support to your blog. Features include: media player, 3rd party statistics and iTunes integration.
|
6 |
+
Version: 0.2.0
|
7 |
+
Author: Blubrry
|
8 |
+
Author URI: http://www.blubrry.com/
|
9 |
+
Change Log:
|
10 |
+
2008-08-05 - v0.2.0: First beta release of Blubrry Powerpress plugin.
|
11 |
+
2008-08-05 - v0.1.2: Fixed minor bugs, trimming empty hour values in duration.
|
12 |
+
2008-08-04 - v0.1.1: Fixed minor bugs, PHP_EOL define, check if function exists for older versions of wordpress and more.
|
13 |
+
2008-08-04 - v0.1.0: Tentative initial release of Blubrry Powerpress plugin.
|
14 |
+
|
15 |
+
Contributors:
|
16 |
+
Angelo Mandato, CIO RawVoice - Plugin founder and architect, mp3info class and javascript media player
|
17 |
+
Pat McSweeny, Developer for RawVoice - powerpress.php and powperpressoptions.php
|
18 |
+
|
19 |
+
Credits:
|
20 |
+
getID3(), License: GPL 2.0+ by James Heinrich <info [at] getid3.org> http://www.getid3.org
|
21 |
+
Note: getid3.php analyze() function modified to prevent redundant filesize() function call.
|
22 |
+
FlowPlayer, License: GPL 3.0+ http://flowplayer.org/; source: http://flowplayer.org/download.html
|
23 |
+
flashembed(), License: MIT by Tero Piirainen (tipiirai [at] gmail.com)
|
24 |
+
Note: code found at bottom of player.js
|
25 |
+
|
26 |
+
Copyright 2008 RawVoice Inc. (http://www.rawvoice.com)
|
27 |
+
|
28 |
+
License: Apache License version 2.0 (http://www.apache.org/licenses/)
|
29 |
+
|
30 |
+
This project uses source that is GPL licensed that, for the sake of this plugin,
|
31 |
+
is interpreted as GPL version 3.0 for compatibility with Apache 2.0 license.
|
32 |
+
*/
|
33 |
+
|
34 |
+
define('POWERPRESS_VERSION', '0.1.1' );
|
35 |
+
|
36 |
+
// Define variables, advanced users could define these in their own wp-config.php so lets not try to re-define
|
37 |
+
if( !defined('POWERPRESS_PLUGIN_PATH') )
|
38 |
+
define('POWERPRESS_PLUGIN_PATH', '/wp-content/plugins/powerpress/');
|
39 |
+
if( !defined('POWERPRESS_LINK_SEPARATOR') )
|
40 |
+
define('POWERPRESS_LINK_SEPARATOR', '|');
|
41 |
+
if( !defined('PHP_EOL') )
|
42 |
+
define('PHP_EOL', "\n"); // We need this variable defined for new lines.
|
43 |
+
|
44 |
+
function powerpress_content($content)
|
45 |
+
{
|
46 |
+
global $post;
|
47 |
+
|
48 |
+
if( is_feed() )
|
49 |
+
return $content; // We don't want to do anything to the feed
|
50 |
+
|
51 |
+
// Powerpress settings:
|
52 |
+
$Powerpress = get_option('powerpress_general');
|
53 |
+
|
54 |
+
// Get the enclosure data
|
55 |
+
$enclosureData = get_post_meta($post->ID, 'enclosure', true);
|
56 |
+
|
57 |
+
if( !$enclosureData )
|
58 |
+
{
|
59 |
+
$EnclosureURL = '';
|
60 |
+
if( $Powerpress['process_podpress'] )
|
61 |
+
{
|
62 |
+
//$Settings = get_option('powerpress_general');
|
63 |
+
$podPressMedia = get_post_meta($post->ID, 'podPressMedia', true);
|
64 |
+
if( $podPressMedia )
|
65 |
+
$EnclosureURL = $podPressMedia[0]['URI'];
|
66 |
+
if( !$EnclosureURL )
|
67 |
+
return $content;
|
68 |
+
if( strpos($EnclosureURL, 'http://' ) !== 0 )
|
69 |
+
$EnclosureURL = $Powerpress['default_url'] . $EnclosureURL;
|
70 |
+
}
|
71 |
+
}
|
72 |
+
else
|
73 |
+
{
|
74 |
+
list($EnclosureURL, $EnclosureSize, $EnclosureType) = split("\n", $enclosureData);
|
75 |
+
$EnclosureURL = trim($EnclosureURL);
|
76 |
+
}
|
77 |
+
|
78 |
+
// Just in case, if there's no URL lets escape!
|
79 |
+
if( !$EnclosureURL )
|
80 |
+
return $content;
|
81 |
+
|
82 |
+
|
83 |
+
if( !isset($Powerpress['display_player']) )
|
84 |
+
$Powerpress['display_player'] = 1;
|
85 |
+
if( !isset($Powerpress['player_function']) )
|
86 |
+
$Powerpress['player_function'] = 1;
|
87 |
+
if( !isset($Powerpress['podcast_link']) )
|
88 |
+
$Powerpress['podcast_link'] = 1;
|
89 |
+
|
90 |
+
// The blog owner doesn't want anything displayed, so don't bother wasting anymore CPU cycles
|
91 |
+
if( $Powerpress['display_player'] == 0 )
|
92 |
+
return $content;
|
93 |
+
|
94 |
+
// Create the redirect URL
|
95 |
+
$EnclosureURL = 'http://' .str_replace('http://', '', $Powerpress['redirect1'] . $Powerpress['redirect2'] . $Powerpress['redirect3'] . $EnclosureURL );
|
96 |
+
|
97 |
+
// Build links for player
|
98 |
+
$player_links = '';
|
99 |
+
switch( $Powerpress['player_function'] )
|
100 |
+
{
|
101 |
+
case 1: { // On page and new window
|
102 |
+
//$player_links .= "<a href=\"$EnclosureURL\" title=\"Play in page\" onclick=\"return bpPlayer.PlayInPage(this.href, 'powerpress_player_{$post->ID}');\">Play in page</a>".PHP_EOL;
|
103 |
+
//$player_links .= " ".POWERPRESS_LINK_SEPARATOR." ";
|
104 |
+
$player_links .= "<a href=\"$EnclosureURL\" title=\"Play in new window\" onclick=\"return bpPlayer.PlayNewWindow(this.href);\">Play in new window</a>".PHP_EOL;
|
105 |
+
}; break;
|
106 |
+
case 2: { // Play in page only
|
107 |
+
//$player_links .= "<a href=\"$EnclosureURL\" title=\"Play in page\" onclick=\"return bpPlayer.PlayInPage(this.href, 'powerpress_player_{$post->ID}');\">Play in page</a>".PHP_EOL;
|
108 |
+
}; break;
|
109 |
+
case 3: { //Play in new window only
|
110 |
+
$player_links .= "<a href=\"$EnclosureURL\" title=\"Play in new window\" onclick=\"return bpPlayer.PlayNewWindow(this.href);\">Play in new window</a>".PHP_EOL;
|
111 |
+
}; break;
|
112 |
+
}//end switch
|
113 |
+
|
114 |
+
if( $Powerpress['podcast_link'] == 1 )
|
115 |
+
{
|
116 |
+
if( $player_links )
|
117 |
+
$player_links .= ' '. POWERPRESS_LINK_SEPARATOR .' ';
|
118 |
+
$player_links .= "<a href=\"$EnclosureURL\" title=\"Download\">Download</a>".PHP_EOL;
|
119 |
+
}
|
120 |
+
|
121 |
+
$new_content = '';
|
122 |
+
if( $Powerpress['player_function'] == 1 || $Powerpress['player_function'] == 2 ) // We have some kind of on-line player
|
123 |
+
{
|
124 |
+
$new_content .= '<div class="powerpress_player" id="powerpress_player_'. $post->ID .'"></div>'.PHP_EOL;
|
125 |
+
$new_content .= '<script type="text/javascript">'.PHP_EOL;
|
126 |
+
$new_content .= "bpPlayer.PlayInPage('$EnclosureURL', 'powerpress_player_{$post->ID}');\n";
|
127 |
+
$new_content .= '</script>'.PHP_EOL;
|
128 |
+
}
|
129 |
+
if( $player_links )
|
130 |
+
$new_content .= '<p class="powerpress_links">Podcast: ' . $player_links . '</p>'.PHP_EOL;
|
131 |
+
|
132 |
+
if( $new_content == '' )
|
133 |
+
return $content;
|
134 |
+
|
135 |
+
switch( $Powerpress['display_player'] )
|
136 |
+
{
|
137 |
+
case 1: { // Below posts
|
138 |
+
return $content.$new_content;
|
139 |
+
}; break;
|
140 |
+
case 2: { // Above posts
|
141 |
+
return $new_content.$content;
|
142 |
+
}; break;
|
143 |
+
}
|
144 |
+
}//end function
|
145 |
+
|
146 |
+
add_action('the_content', 'powerpress_content');
|
147 |
+
|
148 |
+
function powerpress_header()
|
149 |
+
{
|
150 |
+
$PowerpressPluginURL = powerpress_get_root_url();
|
151 |
+
?>
|
152 |
+
<script type="text/javascript" src="<?php echo $PowerpressPluginURL; ?>player.js"></script>
|
153 |
+
<script type="text/javascript">
|
154 |
+
var bpPlayer = new jsMediaPlayer('<?php echo $PowerpressPluginURL; ?>FlowPlayerClassic.swf');
|
155 |
+
</script>
|
156 |
+
<style type="text/css">
|
157 |
+
.powerpress_player_old {
|
158 |
+
margin-bottom: 3px;
|
159 |
+
margin-top: 10px;
|
160 |
+
}
|
161 |
+
</style>
|
162 |
+
<?php
|
163 |
+
}
|
164 |
+
|
165 |
+
add_action('wp_head', 'powerpress_header');
|
166 |
+
|
167 |
+
function powerpress_rss2_ns(){
|
168 |
+
if( defined('PODPRESS_VERSION') || isset($GLOBALS['podcasting_player_id']) )
|
169 |
+
return; // Another podcasting plugin is enabled...
|
170 |
+
|
171 |
+
// Okay, lets add the namespace
|
172 |
+
echo 'xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"'."\n";
|
173 |
+
}
|
174 |
+
|
175 |
+
add_action('rss2_ns', 'powerpress_rss2_ns');
|
176 |
+
|
177 |
+
|
178 |
+
function powerpress_rss2_head()
|
179 |
+
{
|
180 |
+
global $powerpress_feed, $powerpress_itunes_explicit, $powerpress_itunes_talent_name, $powerpress_default_url, $powerpress_process_podpress;
|
181 |
+
$powerpress_feed = false; // By default, lets not apply the feed settings...
|
182 |
+
|
183 |
+
if( defined('PODPRESS_VERSION') || isset($GLOBALS['podcasting_player_id']) )
|
184 |
+
return; // Another podcasting plugin is enabled...
|
185 |
+
|
186 |
+
|
187 |
+
$feed = get_query_var( 'feed' );
|
188 |
+
if( $feed != 'feed' && $feed != 'podcast' && $feed != 'rss2' )
|
189 |
+
return; // This is definitely not our kind of feed
|
190 |
+
|
191 |
+
$GeneralSettings = get_option('powerpress_general');
|
192 |
+
$powerpress_default_url = $GeneralSettings['default_url'];
|
193 |
+
$powerpress_process_podpress = $GeneralSettings['process_podpress'];
|
194 |
+
|
195 |
+
$Feed = get_option('powerpress_feed');
|
196 |
+
|
197 |
+
// First, determine if powerpress should even be rewriting this feed...
|
198 |
+
if( $Feed['apply_to'] == '0' )
|
199 |
+
return; // Okay, we're not suppoed to touch this feed, it's bad enough we added the iTunes namespace, escape!!!
|
200 |
+
|
201 |
+
if( $Feed['apply_to'] == '3' && $feed != 'podcast' )
|
202 |
+
return; // This is definitely not our kind of feed
|
203 |
+
|
204 |
+
if( $Feed['apply_to'] == '2' && $feed != 'podcast' )
|
205 |
+
{
|
206 |
+
// If there's anything else in the query string, then something's going on and we shouldn't touch the feed
|
207 |
+
if( isset($GLOBALS['wp_query']->query_vars) && count($GLOBALS['wp_query']->query_vars) > 1 )
|
208 |
+
return;
|
209 |
+
}
|
210 |
+
|
211 |
+
// if( $Feed['apply_to'] == '1' ) { } // continue...
|
212 |
+
// Case 1 (default, we apply to all of the rss2 feeds...)
|
213 |
+
|
214 |
+
// We made it this far, lets write stuff to the feed!
|
215 |
+
$powerpress_feed = true; // Okay, lets continue...
|
216 |
+
if( $Feed )
|
217 |
+
{
|
218 |
+
while( list($key,$value) = each($Feed) )
|
219 |
+
$Feed[$key] = htmlentities($value, ENT_NOQUOTES, 'UTF-8');
|
220 |
+
reset($Feed);
|
221 |
+
}
|
222 |
+
|
223 |
+
echo '<!-- podcast_generator="Blubrry Powerpress/'. POWERPRESS_VERSION .'" -->'.PHP_EOL;
|
224 |
+
|
225 |
+
if( defined('POWERPRESS_NEW_FEED_URL') )
|
226 |
+
echo "\t<itunes:new-feed-url>".POWERPRESS_NEW_FEED_URL.'</itunes:new-feed-url>'.PHP_EOL;
|
227 |
+
|
228 |
+
if( $Feed['itunes_summary'] )
|
229 |
+
echo "\t".'<itunes:summary>'. htmlentities( $Feed['itunes_summary'], ENT_NOQUOTES, 'UTF-8') .'</itunes:summary>'.PHP_EOL;
|
230 |
+
else
|
231 |
+
echo "\t".'<itunes:summary>'. htmlentities( get_bloginfo('description'), ENT_NOQUOTES, 'UTF-8') .'</itunes:summary>'.PHP_EOL;
|
232 |
+
|
233 |
+
// explicit options:
|
234 |
+
$explicit = array("no", "yes", "clean");
|
235 |
+
|
236 |
+
$powerpress_itunes_explicit = $explicit[$Feed['itunes_explicit']];
|
237 |
+
$powerpress_itunes_talent_name = $Feed['itunes_talent_name'];
|
238 |
+
|
239 |
+
if( $powerpress_itunes_explicit )
|
240 |
+
echo "\t".'<itunes:explicit>' . $powerpress_itunes_explicit . '</itunes:explicit>'.PHP_EOL;
|
241 |
+
if( $Feed['itunes_image'] )
|
242 |
+
{
|
243 |
+
echo "\t".'<itunes:image href="' . $Feed['itunes_image'] . '" />'.PHP_EOL;
|
244 |
+
}
|
245 |
+
else
|
246 |
+
{
|
247 |
+
echo "\t".'<itunes:image href="' . powerpress_get_root_url() . 'itunes_default.jpg" />'.PHP_EOL;
|
248 |
+
}
|
249 |
+
|
250 |
+
if( $Feed['itunes_talent_name'] && $Feed['email'] )
|
251 |
+
{
|
252 |
+
echo "\t".'<itunes:owner>'.PHP_EOL;
|
253 |
+
echo "\t\t".'<itunes:name>' . $Feed['itunes_talent_name'] . '</itunes:name>'.PHP_EOL;
|
254 |
+
echo "\t\t".'<itunes:email>' . $Feed['email'] . '</itunes:email>'.PHP_EOL;
|
255 |
+
echo "\t".'</itunes:owner>'.PHP_EOL;
|
256 |
+
}
|
257 |
+
if( $Feed['copyright'] )
|
258 |
+
echo "\t".'<copyright>'. str_replace( array('©', '(c)', '(C)'), '©', htmlentities($Feed['copyright'], ENT_NOQUOTES, 'UTF-8')) . '</copyright>'.PHP_EOL;
|
259 |
+
if( $Feed['itunes_subtitle'] )
|
260 |
+
echo "\t".'<itunes:subtitle>' . htmlentities($Feed['itunes_subtitle'], ENT_NOQUOTES, 'UTF-8') . '</itunes:subtitle>'.PHP_EOL;
|
261 |
+
if( $Feed['itunes_keywords'] )
|
262 |
+
echo "\t".'<itunes:keywords>' . htmlentities($Feed['itunes_keywords'], ENT_NOQUOTES, 'UTF-8') . '</itunes:keywords>'.PHP_EOL;
|
263 |
+
if( $Feed['itunes_talent_name'] && $Feed['email'] )
|
264 |
+
echo "\t".'<managingEditor>'. $Feed['email'] .' ('. htmlentities($Feed['itunes_talent_name'], ENT_NOQUOTES, 'UTF-8') .')</managingEditor>'.PHP_EOL;
|
265 |
+
if( $Feed['rss2_image'] )
|
266 |
+
{
|
267 |
+
echo"\t". '<image>' .PHP_EOL;
|
268 |
+
echo "\t\t".'<title>' . htmlentities(get_bloginfo('name'), ENT_NOQUOTES, 'UTF-8') . '</title>'.PHP_EOL;
|
269 |
+
echo "\t\t".'<url>' . $Feed['rss2_image'] . '</url>'.PHP_EOL;
|
270 |
+
echo "\t\t".'<link>'. get_bloginfo('url') . '</link>' . PHP_EOL;
|
271 |
+
echo "\t".'</image>' . PHP_EOL;
|
272 |
+
}
|
273 |
+
else // Use the default image
|
274 |
+
{
|
275 |
+
echo"\t". '<image>' .PHP_EOL;
|
276 |
+
echo "\t\t".'<title>' . htmlentities(get_bloginfo('name'), ENT_NOQUOTES, 'UTF-8') . '</title>'.PHP_EOL;
|
277 |
+
echo "\t\t".'<url>' . powerpress_get_root_url() . 'rss_default.jpg</url>'.PHP_EOL;
|
278 |
+
echo "\t\t".'<link>'. get_bloginfo('url') . '</link>' . PHP_EOL;
|
279 |
+
echo "\t".'</image>' . PHP_EOL;
|
280 |
+
}
|
281 |
+
|
282 |
+
$Categories = powerpress_itunes_categories();
|
283 |
+
$Cat1 = false; $Cat2 = false; $Cat3 = false;
|
284 |
+
if( $Feed['itunes_cat_1'] != '' )
|
285 |
+
list($Cat1, $SubCat1) = split('-', $Feed['itunes_cat_1']);
|
286 |
+
if( $Feed['itunes_cat_2'] != '' )
|
287 |
+
list($Cat2, $SubCat2) = split('-', $Feed['itunes_cat_2']);
|
288 |
+
if( $Feed['itunes_cat_3'] != '' )
|
289 |
+
list($Cat3, $SubCat3) = split('-', $Feed['itunes_cat_3']);
|
290 |
+
|
291 |
+
if( $Cat1 )
|
292 |
+
{
|
293 |
+
$CatDesc = $Categories[$Cat1.'-00'];
|
294 |
+
$SubCatDesc = $Categories[$Cat1.'-'.$SubCat1];
|
295 |
+
if( $Cat1 != $Cat2 && $SubCat1 == '00' )
|
296 |
+
{
|
297 |
+
echo "\t".'<itunes:category text="'. htmlspecialchars($CatDesc) .'" />'.PHP_EOL;
|
298 |
+
}
|
299 |
+
else
|
300 |
+
{
|
301 |
+
echo "\t".'<itunes:category text="'. htmlspecialchars($CatDesc) .'">'.PHP_EOL;
|
302 |
+
if( $SubCat1 != '00' )
|
303 |
+
echo "\t\t".'<itunes:category text="'. htmlspecialchars($SubCatDesc) .'" />'.PHP_EOL;
|
304 |
+
|
305 |
+
// End this category set
|
306 |
+
if( $Cat1 != $Cat2 )
|
307 |
+
echo "\t".'</itunes:category>'.PHP_EOL;
|
308 |
+
}
|
309 |
+
}
|
310 |
+
|
311 |
+
if( $Cat2 )
|
312 |
+
{
|
313 |
+
$CatDesc = $Categories[$Cat2.'-00'];
|
314 |
+
$SubCatDesc = $Categories[$Cat2.'-'.$SubCat2];
|
315 |
+
|
316 |
+
// It's a continuation of the last category...
|
317 |
+
if( $Cat1 == $Cat2 )
|
318 |
+
{
|
319 |
+
if( $SubCat2 != '00' )
|
320 |
+
echo "\t\t".'<itunes:category text="'. htmlspecialchars($SubCatDesc) .'" />'.PHP_EOL;
|
321 |
+
|
322 |
+
// End this category set
|
323 |
+
if( $Cat2 != $Cat3 )
|
324 |
+
echo "\t".'</itunes:category>'.PHP_EOL;
|
325 |
+
}
|
326 |
+
else // This is not a continuation, lets start a new category set
|
327 |
+
{
|
328 |
+
if( $Cat2 != $Cat3 && $SubCat2 == '00' )
|
329 |
+
{
|
330 |
+
echo "\t".'<itunes:category text="'. htmlspecialchars($CatDesc) .'" />'.PHP_EOL;
|
331 |
+
}
|
332 |
+
else // We have nested values
|
333 |
+
{
|
334 |
+
if( $Cat1 != $Cat2 ) // Start a new category set
|
335 |
+
echo "\t".'<itunes:category text="'. htmlspecialchars($CatDesc) .'">'.PHP_EOL;
|
336 |
+
if( $SubCat2 != '00' )
|
337 |
+
echo "\t\t".'<itunes:category text="'. htmlspecialchars($SubCatDesc) .'" />'.PHP_EOL;
|
338 |
+
if( $Cat2 != $Cat3 ) // End this category set
|
339 |
+
echo "\t".'</itunes:category>'.PHP_EOL;
|
340 |
+
}
|
341 |
+
}
|
342 |
+
}
|
343 |
+
|
344 |
+
if( $Cat3 )
|
345 |
+
{
|
346 |
+
$CatDesc = $Categories[$Cat3.'-00'];
|
347 |
+
$SubCatDesc = $Categories[$Cat3.'-'.$SubCat3];
|
348 |
+
|
349 |
+
// It's a continuation of the last category...
|
350 |
+
if( $Cat2 == $Cat3 )
|
351 |
+
{
|
352 |
+
if( $SubCat3 != '00' )
|
353 |
+
echo "\t\t".'<itunes:category text="'. htmlspecialchars($SubCatDesc) .'" />'.PHP_EOL;
|
354 |
+
|
355 |
+
// End this category set
|
356 |
+
echo "\t".'</itunes:category>'.PHP_EOL;
|
357 |
+
}
|
358 |
+
else // This is not a continuation, lets start a new category set
|
359 |
+
{
|
360 |
+
if( $Cat2 != $Cat3 && $SubCat3 == '00' )
|
361 |
+
{
|
362 |
+
echo "\t".'<itunes:category text="'. htmlspecialchars($CatDesc) .'" />'.PHP_EOL;
|
363 |
+
}
|
364 |
+
else // We have nested values
|
365 |
+
{
|
366 |
+
if( $Cat2 != $Cat3 ) // Start a new category set
|
367 |
+
echo "\t".'<itunes:category text="'. htmlspecialchars($CatDesc) .'">'.PHP_EOL;
|
368 |
+
if( $SubCat3 != '00' )
|
369 |
+
echo "\t\t".'<itunes:category text="'. htmlspecialchars($SubCatDesc) .'" />'.PHP_EOL;
|
370 |
+
// End this category set
|
371 |
+
echo "\t".'</itunes:category>'.PHP_EOL;
|
372 |
+
}
|
373 |
+
}
|
374 |
+
}
|
375 |
+
}
|
376 |
+
|
377 |
+
add_action('rss2_head', 'powerpress_rss2_head');
|
378 |
+
|
379 |
+
function powerpress_rss2_item()
|
380 |
+
{
|
381 |
+
global $powerpress_feed, $powerpress_itunes_explicit, $powerpress_itunes_talent_name, $powerpress_default_url, $powerpress_process_podpress, $post;
|
382 |
+
$duration = false;
|
383 |
+
// are we processing a feed that powerpress should handle
|
384 |
+
if( $powerpress_feed == false )
|
385 |
+
return;
|
386 |
+
|
387 |
+
// Check and see if we're working with a podcast episode
|
388 |
+
$enclosureData = get_post_meta($post->ID, 'enclosure', true);
|
389 |
+
if( !$enclosureData )
|
390 |
+
{
|
391 |
+
$EnclosureURL = '';
|
392 |
+
if( $powerpress_process_podpress )
|
393 |
+
{
|
394 |
+
//$Settings = get_option('powerpress_general');
|
395 |
+
$podPressMedia = get_post_meta($post->ID, 'podPressMedia', true);
|
396 |
+
if( $podPressMedia )
|
397 |
+
{
|
398 |
+
$EnclosureURL = $podPressMedia[0]['URI'];
|
399 |
+
if( strpos($EnclosureURL, 'http://' ) !== 0 )
|
400 |
+
$EnclosureURL = $powerpress_default_url . $EnclosureURL;
|
401 |
+
$EnclosureSize = $podPressMedia[0]['size'];
|
402 |
+
$duration = $podPressMedia[0]['duration'];
|
403 |
+
$EnclosureType = false;
|
404 |
+
$UrlParts = parse_url($EnclosureURL);
|
405 |
+
if( $UrlParts['path'] )
|
406 |
+
{
|
407 |
+
// using functions that already exist in Wordpress when possible:
|
408 |
+
$FileType = wp_check_filetype($UrlParts['path']);
|
409 |
+
if( $FileType )
|
410 |
+
$EnclosureType = $FileType['type'];
|
411 |
+
}
|
412 |
+
|
413 |
+
if( $EnclosureType && $EnclosureSize && $EnclosureURL )
|
414 |
+
echo "\t\t".'<enclosure url="' . $EnclosureURL . '" length="'. $EnclosureSize .'" type="'. $EnclosureType .'" />'.PHP_EOL;
|
415 |
+
else
|
416 |
+
return;
|
417 |
+
}
|
418 |
+
else
|
419 |
+
return;
|
420 |
+
}
|
421 |
+
else
|
422 |
+
return;
|
423 |
+
}
|
424 |
+
|
425 |
+
if( !$duration )
|
426 |
+
$duration = get_post_meta($post->ID, 'itunes:duration', true);
|
427 |
+
|
428 |
+
// Get the post tags:
|
429 |
+
$tagobject = wp_get_post_tags( $post->ID );
|
430 |
+
if( count($tagobject) )
|
431 |
+
{
|
432 |
+
$tags = array();
|
433 |
+
for($c = 0; $c < count($tagobject) && $c < 12; $c++) // iTunes only accepts up to 12 keywords
|
434 |
+
$tags[] = htmlentities($tagobject[$c]->name, ENT_NOQUOTES, 'UTF-8');
|
435 |
+
|
436 |
+
echo "\t\t<itunes:keywords>" . implode(",", $tags) . '</itunes:keywords>'.PHP_EOL;
|
437 |
+
}
|
438 |
+
|
439 |
+
$content_no_html = strip_tags($post->post_content);
|
440 |
+
|
441 |
+
echo "\t\t<itunes:subtitle>". powerpress_smart_trim($content_no_html, 250, true) .'</itunes:subtitle>'.PHP_EOL;
|
442 |
+
if( defined('POWERPRESS_ITEM_SUMMARY') )
|
443 |
+
echo "\t\t<itunes:summary>". powerpress_smart_trim($content_no_html, 4000) .'</itunes:summary>'.PHP_EOL;
|
444 |
+
if( $powerpress_itunes_talent_name )
|
445 |
+
echo "\t\t<itunes:author>" . $powerpress_itunes_talent_name . '</itunes:author>'.PHP_EOL;
|
446 |
+
|
447 |
+
if( $powerpress_itunes_explicit )
|
448 |
+
echo "\t\t<itunes:explicit>" . $powerpress_itunes_explicit . '</itunes:explicit>'.PHP_EOL;
|
449 |
+
|
450 |
+
if( $duration && preg_match('/^(\d{1,2}:){0,2}\d{1,2}$/i', $duration) ) // Include duration if it is valid
|
451 |
+
echo "\t\t<itunes:duration>" . ltrim($duration, '0:') . '</itunes:duration>'.PHP_EOL;
|
452 |
+
}
|
453 |
+
|
454 |
+
add_action('rss2_item', 'powerpress_rss2_item');
|
455 |
+
|
456 |
+
function powerpress_filter_rss_enclosure($content)
|
457 |
+
{
|
458 |
+
// Add the redirect url if there is one...
|
459 |
+
$RedirectURL = powerpress_get_redirect_url();
|
460 |
+
if( $RedirectURL )
|
461 |
+
$content = str_replace('http://', $RedirectURL, $content);
|
462 |
+
return $content;
|
463 |
+
}
|
464 |
+
|
465 |
+
add_filter('rss_enclosure', 'powerpress_filter_rss_enclosure');
|
466 |
+
|
467 |
+
function powerpress_do_podcast_feed()
|
468 |
+
{
|
469 |
+
global $wp_query;
|
470 |
+
$wp_query->get_posts();
|
471 |
+
load_template(ABSPATH . 'wp-rss2.php');
|
472 |
+
}
|
473 |
+
|
474 |
+
function powerpress_init()
|
475 |
+
{
|
476 |
+
add_feed('podcast', 'powerpress_do_podcast_feed');
|
477 |
+
}
|
478 |
+
|
479 |
+
add_action('init', 'powerpress_init');
|
480 |
+
|
481 |
+
|
482 |
+
function powerpress_posts_join($join) {
|
483 |
+
if ( is_feed() && get_query_var('feed') == 'podcast' ) {
|
484 |
+
global $wpdb;
|
485 |
+
// Future feature: only display posts that have enclosures...
|
486 |
+
// $query->set('cat','-20,-21,-22');
|
487 |
+
//$join .= " LEFT JOIN {$wpdb->postmeta} ";
|
488 |
+
//$join .= " ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = 'enclosure' ";
|
489 |
+
// $wpdb->postmeta
|
490 |
+
}
|
491 |
+
return $join;
|
492 |
+
}
|
493 |
+
|
494 |
+
add_filter('posts_join', 'powerpress_posts_join' );
|
495 |
+
|
496 |
+
//add_filter('pre_get_posts','my_cat_exclude');
|
497 |
+
|
498 |
+
/*
|
499 |
+
Helper functions:
|
500 |
+
*/
|
501 |
+
|
502 |
+
function powerpress_itunes_categories($PrefixSubCategories = false)
|
503 |
+
{
|
504 |
+
$temp = array();
|
505 |
+
$temp['01-00'] = 'Arts';
|
506 |
+
$temp['01-01'] = 'Design';
|
507 |
+
$temp['01-02'] = 'Fashion & Beauty';
|
508 |
+
$temp['01-03'] = 'Food';
|
509 |
+
$temp['01-04'] = 'Literature';
|
510 |
+
$temp['01-05'] = 'Performing Arts';
|
511 |
+
$temp['01-06'] = 'Visual Arts';
|
512 |
+
|
513 |
+
$temp['02-00'] = 'Business';
|
514 |
+
$temp['02-01'] = 'Business News';
|
515 |
+
$temp['02-02'] = 'Careers';
|
516 |
+
$temp['02-03'] = 'Investing';
|
517 |
+
$temp['02-04'] = 'Management & Marketing';
|
518 |
+
$temp['02-05'] = 'Shopping';
|
519 |
+
|
520 |
+
$temp['03-00'] = 'Comedy';
|
521 |
+
|
522 |
+
$temp['04-00'] = 'Education';
|
523 |
+
$temp['04-01'] = 'Education Technology';
|
524 |
+
$temp['04-02'] = 'Higher Education';
|
525 |
+
$temp['04-03'] = 'K-12';
|
526 |
+
$temp['04-04'] = 'Language Courses';
|
527 |
+
$temp['04-05'] = 'Training';
|
528 |
+
|
529 |
+
$temp['05-00'] = 'Games & Hobbies';
|
530 |
+
$temp['05-01'] = 'Automotive';
|
531 |
+
$temp['05-02'] = 'Aviation';
|
532 |
+
$temp['05-03'] = 'Hobbies';
|
533 |
+
$temp['05-04'] = 'Other Games';
|
534 |
+
$temp['05-05'] = 'Video Games';
|
535 |
+
|
536 |
+
$temp['06-00'] = 'Government & Organizations';
|
537 |
+
$temp['06-01'] = 'Local';
|
538 |
+
$temp['06-02'] = 'National';
|
539 |
+
$temp['06-03'] = 'Non-Profit';
|
540 |
+
$temp['06-04'] = 'Regional';
|
541 |
+
|
542 |
+
$temp['07-00'] = 'Health';
|
543 |
+
$temp['07-01'] = 'Alternative Health';
|
544 |
+
$temp['07-02'] = 'Fitness & Nutrition';
|
545 |
+
$temp['07-03'] = 'Self-Help';
|
546 |
+
$temp['07-04'] = 'Sexuality';
|
547 |
+
|
548 |
+
$temp['08-00'] = 'Kids & Family';
|
549 |
+
|
550 |
+
$temp['09-00'] = 'Music';
|
551 |
+
|
552 |
+
$temp['10-00'] = 'News & Politics';
|
553 |
+
|
554 |
+
$temp['11-00'] = 'Religion & Spirituality';
|
555 |
+
$temp['11-01'] = 'Buddhism';
|
556 |
+
$temp['11-02'] = 'Christianity';
|
557 |
+
$temp['11-03'] = 'Hinduism';
|
558 |
+
$temp['11-04'] = 'Islam';
|
559 |
+
$temp['11-05'] = 'Judaism';
|
560 |
+
$temp['11-06'] = 'Other';
|
561 |
+
$temp['11-07'] = 'Spirituality';
|
562 |
+
|
563 |
+
$temp['12-00'] = 'Science & Medicine';
|
564 |
+
$temp['12-01'] = 'Medicine';
|
565 |
+
$temp['12-02'] = 'Natural Sciences';
|
566 |
+
$temp['12-03'] = 'Social Sciences';
|
567 |
+
|
568 |
+
$temp['13-00'] = 'Society & Culture';
|
569 |
+
$temp['13-01'] = 'History';
|
570 |
+
$temp['13-02'] = 'Personal Journals';
|
571 |
+
$temp['13-03'] = 'Philosophy';
|
572 |
+
$temp['13-04'] = 'Places & Travel';
|
573 |
+
|
574 |
+
$temp['14-00'] = 'Sports & Recreation';
|
575 |
+
$temp['14-01'] = 'Amateur';
|
576 |
+
$temp['14-02'] = 'College & High School';
|
577 |
+
$temp['14-03'] = 'Outdoor';
|
578 |
+
$temp['14-04'] = 'Professional';
|
579 |
+
|
580 |
+
$temp['15-00'] = 'Technology';
|
581 |
+
$temp['15-01'] = 'Gadgets';
|
582 |
+
$temp['15-02'] = 'Tech News';
|
583 |
+
$temp['15-03'] = 'Podcasting';
|
584 |
+
$temp['15-04'] = 'Software How-To';
|
585 |
+
|
586 |
+
$temp['16-00'] = 'TV & Film';
|
587 |
+
|
588 |
+
if( $PrefixSubCategories )
|
589 |
+
{
|
590 |
+
while( list($key,$val) = each($temp) )
|
591 |
+
{
|
592 |
+
$parts = split('-', $key);
|
593 |
+
$cat = $parts[0];
|
594 |
+
$subcat = $parts[1];
|
595 |
+
|
596 |
+
if( $subcat != '00' )
|
597 |
+
$temp[$key] = $temp[$cat.'-00'].' > '.$val;
|
598 |
+
}
|
599 |
+
reset($temp);
|
600 |
+
}
|
601 |
+
|
602 |
+
return $temp;
|
603 |
+
}
|
604 |
+
|
605 |
+
function powerpress_get_root_url()
|
606 |
+
{
|
607 |
+
return get_bloginfo('url') . POWERPRESS_PLUGIN_PATH;
|
608 |
+
}
|
609 |
+
|
610 |
+
function powerpress_smart_trim($value, $char_limit = 250, $remove_new_lines = false)
|
611 |
+
{
|
612 |
+
if( strlen($value) > $char_limit )
|
613 |
+
{
|
614 |
+
$new_value = substr($new_value, 0, $char_limit);
|
615 |
+
// Look back at most 50 characters...
|
616 |
+
$eos = strrpos($new_value, '.');
|
617 |
+
$eol = strrpos($new_value, "\n");
|
618 |
+
// If the end of line is longer than the end of sentence and we're not loosing too much of our string...
|
619 |
+
if( $eol > $eos && $eol > (strlen($new_value)-50) )
|
620 |
+
$return = substr($new_value, 0, $eol);
|
621 |
+
// If the end of sentence is longer than the end of line and we're not loosing too much of our string...
|
622 |
+
else if( $eos > $eol && $eos > (strlen($new_value)-50) )
|
623 |
+
$return = substr($new_value, 0, $eos);
|
624 |
+
else // Otherwise, just add some dots to the end
|
625 |
+
$return = substr($new_value, 0, -3).'...';
|
626 |
+
}
|
627 |
+
else
|
628 |
+
{
|
629 |
+
$return = $value;
|
630 |
+
}
|
631 |
+
|
632 |
+
if( $remove_new_lines )
|
633 |
+
$return = str_replace( array("\n", "\r", "\t"), array(' ', '', ' '), $return );
|
634 |
+
return $return;
|
635 |
+
}
|
636 |
+
|
637 |
+
function powerpress_get_redirect_url()
|
638 |
+
{
|
639 |
+
global $powerpress_redirect_url;
|
640 |
+
if( !isset($powerpress_redirect_url) )
|
641 |
+
{
|
642 |
+
$Powerpress = get_option('powerpress_general');
|
643 |
+
$powerpress_redirect_url = 'http://' .str_replace('http://', '', $Powerpress['redirect1'] . $Powerpress['redirect2'] . $Powerpress['redirect3'] );
|
644 |
+
}
|
645 |
+
return $powerpress_redirect_url;
|
646 |
+
}
|
647 |
+
/*
|
648 |
+
End Helper Functions
|
649 |
+
*/
|
650 |
+
|
651 |
+
// Are we in the admin?
|
652 |
+
if( is_admin() )
|
653 |
+
require_once('powerpressadmin.php');
|
654 |
+
|
655 |
+
?>
|
powerpressadmin.php
ADDED
@@ -0,0 +1,970 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
function powerpress_admin_menu() {
|
4 |
+
if( function_exists('add_meta_box') ) // Otherwise we're using a version of wordpress that is not supported.
|
5 |
+
add_meta_box('id', 'Podcast Episode', 'powerpress_meta_box', 'post', 'normal');
|
6 |
+
add_options_page('Blubrry Powerpress Settings', 'Blubrry Powerpress', 8, 'powerpress/powerpress.php', 'powerpress_admin_page');
|
7 |
+
}
|
8 |
+
|
9 |
+
add_action('admin_menu', 'powerpress_admin_menu');
|
10 |
+
|
11 |
+
function powerpress_meta_box($object, $box)
|
12 |
+
{
|
13 |
+
$DurationHH = '';
|
14 |
+
$DurationMM = '';
|
15 |
+
$DurationSS = '';
|
16 |
+
$EnclosureURL = '';
|
17 |
+
$EnclosureLength = '';
|
18 |
+
|
19 |
+
if( $object->ID )
|
20 |
+
{
|
21 |
+
$enclosureArray = get_post_meta($object->ID, 'enclosure', true);
|
22 |
+
list($EnclosureURL, $EnclosureLength, $EnclosureType) = explode("\n", $enclosureArray);
|
23 |
+
$iTunesDuration = get_post_meta($object->ID, 'itunes:duration', true);
|
24 |
+
list($DurationHH, $DurationMM, $DurationSS) = explode(':', $iTunesDuration);
|
25 |
+
}
|
26 |
+
|
27 |
+
if( $EnclosureURL )
|
28 |
+
{
|
29 |
+
?>
|
30 |
+
<div>
|
31 |
+
<input type="checkbox" name="Powerpress[change_podcast]" id="powerpress_change" value="1" onchange="javascript:document.getElementById('powerpress_podcast_box').style.display=(this.checked?'block':'none');" /> Modify existing podcast episode
|
32 |
+
</div>
|
33 |
+
<?php
|
34 |
+
}
|
35 |
+
else
|
36 |
+
{
|
37 |
+
echo '<input type="hidden" name="Powerpress[new_podcast]" value="1" />'.PHP_EOL;
|
38 |
+
}
|
39 |
+
?>
|
40 |
+
<style type="text/css">
|
41 |
+
#powerpress_podcast_box {
|
42 |
+
|
43 |
+
}
|
44 |
+
#powerpress_podcast_box label {
|
45 |
+
width: 120px;
|
46 |
+
font-weight: bold;
|
47 |
+
font-size: 110%;
|
48 |
+
display: inline;
|
49 |
+
position: absolute;
|
50 |
+
top: 0;
|
51 |
+
left: 0;
|
52 |
+
}
|
53 |
+
#powerpress_podcast_box .powerpress_row {
|
54 |
+
margin-top: 10px;
|
55 |
+
margin-bottom: 10px;
|
56 |
+
position: relative;
|
57 |
+
}
|
58 |
+
#powerpress_podcast_box .powerpress_row_content {
|
59 |
+
margin-left: 120px;
|
60 |
+
}
|
61 |
+
</style>
|
62 |
+
<div id="powerpress_podcast_box"<?php if( $EnclosureURL ) echo ' style="display:none;"'; ?>>
|
63 |
+
<?php
|
64 |
+
if( $EnclosureURL )
|
65 |
+
{
|
66 |
+
?>
|
67 |
+
<div class="powerpress_row">
|
68 |
+
<label>Remove</label>
|
69 |
+
<div class="powerpress_row_content">
|
70 |
+
<input type="checkbox" name="Powerpress[remove_podcast]" id="powerpress_remove" value="1" onchange="javascript:document.getElementById('powerpress_podcast_edit').style.display=(this.checked?'none':'block');" />
|
71 |
+
Podcast episode will be removed from this post upon save
|
72 |
+
</div>
|
73 |
+
</div>
|
74 |
+
<?php
|
75 |
+
}
|
76 |
+
?>
|
77 |
+
<div id="powerpress_podcast_edit">
|
78 |
+
<div class="powerpress_row">
|
79 |
+
<label for "Powerpress[url]">Media URL</label>
|
80 |
+
<div class="powerpress_row_content">
|
81 |
+
<input id="powerpress_url" name="Powerpress[url]" value="<?php echo $EnclosureURL; ?>" style="width: 70%; font-size: 90%;" />
|
82 |
+
</div>
|
83 |
+
</div>
|
84 |
+
<div class="powerpress_row">
|
85 |
+
<label for "size">File Size</label>
|
86 |
+
<div class="powerpress_row_content">
|
87 |
+
<div style="margin-bottom: 4px;">
|
88 |
+
<input id="powerpress_set_size" name="Powerpress[set_size]" value="0" type="radio" checked /> Auto detect file size
|
89 |
+
</div>
|
90 |
+
<div>
|
91 |
+
<input id="powerpress_set_size" name="Powerpress[set_size]" value="1" type="radio" /> Specify:
|
92 |
+
<input id="powerpress_size" name="Powerpress[size]" value="<?php echo $EnclosureLength; ?>" style="width: 110px; font-size: 90%;" /> in bytes
|
93 |
+
</div>
|
94 |
+
</div>
|
95 |
+
</div>
|
96 |
+
<div class="powerpress_row">
|
97 |
+
<label for "size">Duration</label>
|
98 |
+
<div class="powerpress_row_content">
|
99 |
+
<div style="margin-bottom: 4px;">
|
100 |
+
<input id="powerpress_set_duration" name="Powerpress[set_duration]" value="0" type="radio" checked /> Auto detect duration (mp3's only)
|
101 |
+
</div>
|
102 |
+
<div style="margin-bottom: 4px;">
|
103 |
+
<input id="powerpress_set_duration" name="Powerpress[set_duration]" value="1" type="radio" /> Specify:
|
104 |
+
<input id="powerpress_duration_hh" name="Powerpress[duration_hh]" maxlength="2" value="<?php echo $DurationHH; ?>" style="width: 24px; font-size: 90%; text-align: right;" /><strong>:</strong>
|
105 |
+
<input id="powerpress_duration_mm" name="Powerpress[duration_mm]" maxlength="2" value="<?php echo $DurationMM; ?>" style="width: 24px; font-size: 90%; text-align: right;" /><strong>:</strong>
|
106 |
+
<input id="powerpress_duration_ss" name="Powerpress[duration_ss]" maxlength="2" value="<?php echo $DurationSS; ?>" style="width: 24px; font-size: 90%; text-align: right;" /> HH:MM:SS
|
107 |
+
</div>
|
108 |
+
<div>
|
109 |
+
<input id="powerpress_set_duration" name="Powerpress[set_duration]" value="-1" type="radio" /> Not specified
|
110 |
+
</div>
|
111 |
+
</div>
|
112 |
+
</div>
|
113 |
+
</div>
|
114 |
+
</div>
|
115 |
+
<?php
|
116 |
+
}
|
117 |
+
|
118 |
+
|
119 |
+
function powerpress_edit_post($post_ID) {
|
120 |
+
|
121 |
+
$Powerpress = $_POST['Powerpress'];
|
122 |
+
|
123 |
+
if( $Powerpress['remove_podcast'] == 1 )
|
124 |
+
{
|
125 |
+
delete_post_meta( $post_ID, 'enclosure');
|
126 |
+
delete_post_meta( $post_ID, 'itunes:duration');
|
127 |
+
}
|
128 |
+
else if( @$Powerpress['change_podcast'] == 1 || @$Powerpress['new_podcast'] == 1 )
|
129 |
+
{
|
130 |
+
// No URL specified, then it's not really a podcast to save
|
131 |
+
if( $Powerpress['url'] == '' )
|
132 |
+
return;
|
133 |
+
|
134 |
+
// Initialize the important variables:
|
135 |
+
$MediaURL = $Powerpress['url'];
|
136 |
+
if( strpos($MediaURL, 'http://') !== 0 ) // If the url entered does not start with a http://
|
137 |
+
{
|
138 |
+
$Settings = get_option('powerpress_general');
|
139 |
+
$MediaURL = @$Settings['default_url'] . $MediaURL;
|
140 |
+
}
|
141 |
+
|
142 |
+
$FileSize = '';
|
143 |
+
$ContentType = '';
|
144 |
+
$Duration = false;
|
145 |
+
|
146 |
+
// Get the content type based on the file extension, first we have to remove query string if it exists
|
147 |
+
$UrlParts = parse_url($Powerpress['url']);
|
148 |
+
if( $UrlParts['path'] )
|
149 |
+
{
|
150 |
+
// using functions that already exist in Wordpress when possible:
|
151 |
+
$FileType = wp_check_filetype($UrlParts['path']);
|
152 |
+
if( $FileType )
|
153 |
+
$ContentType = $FileType['type'];
|
154 |
+
|
155 |
+
/*
|
156 |
+
$FileParts = pathinfo($UrlParts['path']);
|
157 |
+
if( $FileParts )
|
158 |
+
{
|
159 |
+
|
160 |
+
$ContentType = powerpress_mimetypes($FileParts['extension']);
|
161 |
+
}
|
162 |
+
*/
|
163 |
+
}
|
164 |
+
|
165 |
+
//Set the duration specified by the user
|
166 |
+
if( $Powerpress['set_duration'] == 1 ) // specify duration
|
167 |
+
{
|
168 |
+
$Duration = sprintf('%02d:%02d:%02d', $Powerpress['duration_hh'], $Powerpress['duration_mm'], $Powerpress['duration_ss'] );
|
169 |
+
}
|
170 |
+
|
171 |
+
//Set the file size specified by the user
|
172 |
+
if( $Powerpress['set_size'] == 1 ) // specify file size
|
173 |
+
{
|
174 |
+
$FileSize = $Powerpress['size'];
|
175 |
+
}
|
176 |
+
|
177 |
+
if( $Powerpress['set_size'] == 0 || $Powerpress['set_duration'] == 0 )
|
178 |
+
{
|
179 |
+
// Lets use the mp3info class:
|
180 |
+
require_once('mp3info.class.php');
|
181 |
+
|
182 |
+
$Mp3Info = new Mp3Info();
|
183 |
+
if( $ContentType == 'audio/mpeg' && $Powerpress['set_duration'] == 0 )
|
184 |
+
{
|
185 |
+
$Mp3Data = $Mp3Info->GetMp3Info($MediaURL);
|
186 |
+
if( $Mp3Data )
|
187 |
+
{
|
188 |
+
if( @$Powerpress['set_size'] == 0 )
|
189 |
+
$FileSize = $Mp3Info->GetContentLength();
|
190 |
+
$Duration = $Mp3Data['playtime_string'];
|
191 |
+
if( substr_count($Duration, ':' ) == 0 )
|
192 |
+
{
|
193 |
+
if( $Duration < 60 )
|
194 |
+
$Duration = '00:00:'.$Duration;
|
195 |
+
}
|
196 |
+
else if( substr_count($Duration, ':' ) == 1 )
|
197 |
+
{
|
198 |
+
$Duration = '00:'.$Duration;
|
199 |
+
}
|
200 |
+
}
|
201 |
+
}
|
202 |
+
else // Just get the file size
|
203 |
+
{
|
204 |
+
$Headers = wp_get_http_headers($MediaURL);
|
205 |
+
if( $headers && $headers['content-length'] )
|
206 |
+
{
|
207 |
+
$FileSize = (int) $headers['content-length'];
|
208 |
+
}
|
209 |
+
}
|
210 |
+
}
|
211 |
+
|
212 |
+
$EnclosureData = $MediaURL . "\n" . $FileSize . "\n". $ContentType;
|
213 |
+
|
214 |
+
if( @$Powerpress['new_podcast'] )
|
215 |
+
{
|
216 |
+
add_post_meta($post_ID, 'enclosure', $EnclosureData, true);
|
217 |
+
if( $Duration !== false )
|
218 |
+
add_post_meta($post_ID, 'itunes:duration', $Duration, true);
|
219 |
+
}
|
220 |
+
else
|
221 |
+
{
|
222 |
+
update_post_meta($post_ID, 'enclosure', $EnclosureData);
|
223 |
+
if( $Duration !== false )
|
224 |
+
{
|
225 |
+
if( !update_post_meta($post_ID, 'itunes:duration', $Duration) )
|
226 |
+
add_post_meta($post_ID, 'itunes:duration', $Duration, true); // If we can't update it, lets try to add it
|
227 |
+
}
|
228 |
+
if( $Powerpress['set_duration'] == -1 ) // Special case, lets remove the duration since they set Not specified
|
229 |
+
{
|
230 |
+
delete_post_meta( $post_ID, 'itunes:duration');
|
231 |
+
}
|
232 |
+
}
|
233 |
+
}
|
234 |
+
|
235 |
+
// If we're moving from draft to published, maybe we should ping iTunes?
|
236 |
+
if($_POST['prev_status'] == 'draft' && $_POST['publish'] == 'Publish' )
|
237 |
+
{
|
238 |
+
// Next double check we're looking at a podcast episode...
|
239 |
+
$Enclosure = get_post_meta($post_ID, 'enclosure', true);
|
240 |
+
if( $Enclosure )
|
241 |
+
{
|
242 |
+
$Settings = get_option('powerpress_general');
|
243 |
+
if( $Settings['ping_itunes'] && $Settings['itunes_url'] )
|
244 |
+
{
|
245 |
+
$PingResults = powerpress_ping_itunes($Settings['itunes_url']);
|
246 |
+
//mail( 'email@host.com', 'Ping iTunes Results', implode("\n", $PingResults) ); // Let me know how the ping went.
|
247 |
+
}
|
248 |
+
}
|
249 |
+
}
|
250 |
+
|
251 |
+
// And we're done!
|
252 |
+
}
|
253 |
+
|
254 |
+
add_action('edit_post', 'powerpress_edit_post');
|
255 |
+
|
256 |
+
|
257 |
+
function powerpress_admin_head()
|
258 |
+
{
|
259 |
+
if( strstr($_GET['page'], 'powerpress.php' ) )
|
260 |
+
{
|
261 |
+
echo '<script type="text/javascript">'.PHP_EOL;
|
262 |
+
echo 'function powerpress_show_field(id, show){'.PHP_EOL;
|
263 |
+
echo ' if( document.getElementById(id).nodeName == "SPAN" )'.PHP_EOL;
|
264 |
+
echo ' document.getElementById(id).style.display = (show?"inline":"none");'.PHP_EOL;
|
265 |
+
echo ' else'.PHP_EOL;
|
266 |
+
echo ' document.getElementById(id).style.display = (show?"block":"none");'.PHP_EOL;
|
267 |
+
echo '}'.PHP_EOL;
|
268 |
+
echo '</script>'.PHP_EOL;
|
269 |
+
|
270 |
+
echo '<style type="text/css">'.PHP_EOL;
|
271 |
+
echo '.powerpress-notice {'.PHP_EOL;
|
272 |
+
echo ' margin-top: 10px;'.PHP_EOL;
|
273 |
+
echo ' margin-bottom: 10px;'.PHP_EOL;
|
274 |
+
echo ' line-height: 29px;'.PHP_EOL;
|
275 |
+
echo ' font-size: 12px;'.PHP_EOL;
|
276 |
+
echo ' text-align: center;'.PHP_EOL;
|
277 |
+
echo ' border-width: 1px;'.PHP_EOL;
|
278 |
+
echo ' border-style: solid;'.PHP_EOL;
|
279 |
+
echo ' font-weight: bold;'.PHP_EOL;
|
280 |
+
echo '}'.PHP_EOL;
|
281 |
+
echo '.powerpress-error {'.PHP_EOL;
|
282 |
+
echo ' margin-top: 10px;'.PHP_EOL;
|
283 |
+
echo ' margin-bottom: 10px;'.PHP_EOL;
|
284 |
+
echo ' line-height: 29px;'.PHP_EOL;
|
285 |
+
echo ' font-size: 12px;'.PHP_EOL;
|
286 |
+
echo ' text-align: center;'.PHP_EOL;
|
287 |
+
echo ' border-width: 1px;'.PHP_EOL;
|
288 |
+
echo ' border-style: solid;'.PHP_EOL;
|
289 |
+
echo ' border-color: #c69;'.PHP_EOL;
|
290 |
+
echo ' background-color: #ffeff7;'.PHP_EOL;
|
291 |
+
echo ' font-weight: bold;'.PHP_EOL;
|
292 |
+
echo '}'.PHP_EOL;
|
293 |
+
echo '</style>'.PHP_EOL;
|
294 |
+
}
|
295 |
+
}
|
296 |
+
|
297 |
+
add_action('admin_head', 'powerpress_admin_head');
|
298 |
+
|
299 |
+
function powerpress_admin_page()
|
300 |
+
{
|
301 |
+
global $wp_version;
|
302 |
+
|
303 |
+
$VersionDiff = version_compare($wp_version, 2.5);
|
304 |
+
if( $VersionDiff < 0 )
|
305 |
+
echo '<div class="powerpress-error">Blubrry Powerpress requires Wordpress version 2.5 or greater.</div>';
|
306 |
+
|
307 |
+
|
308 |
+
$UploadArray = wp_upload_dir();
|
309 |
+
$upload_path = rtrim( substr($UploadArray['path'], 0, 0 - strlen($UploadArray['subdir']) ), '\\/').'/powerpress/';
|
310 |
+
|
311 |
+
if( !file_exists($upload_path) )
|
312 |
+
$SupportUploads = @mkdir($upload_path, 0777);
|
313 |
+
else
|
314 |
+
$SupportUploads = true;
|
315 |
+
|
316 |
+
|
317 |
+
|
318 |
+
if( isset($_POST[ 'Submit' ]) )
|
319 |
+
{
|
320 |
+
$urlImages = rtrim( substr($UploadArray['url'], 0, 0 - strlen($UploadArray['subdir']) ), '/').'/powerpress/';
|
321 |
+
|
322 |
+
// Save the posted value in the database
|
323 |
+
$Feed = $_POST['Feed'];
|
324 |
+
$General = $_POST['General'];
|
325 |
+
|
326 |
+
// New iTunes image
|
327 |
+
if( @$_POST['itunes_image_checkbox'] == 1 )
|
328 |
+
{
|
329 |
+
$filename = str_replace(" ", "_", basename($_FILES['itunes_image_file']['name']) );
|
330 |
+
$temp = $_FILES['itunes_image_file']['tmp_name'];
|
331 |
+
|
332 |
+
if( file_exists($upload_path . $filename ) )
|
333 |
+
{
|
334 |
+
$filenameParts = pathinfo($filename);
|
335 |
+
do {
|
336 |
+
$filename_no_ext = substr($filenameParts['basename'], 0, (strlen($filenameParts['extension'])+1) * -1 );
|
337 |
+
$filename = sprintf('%s-%03d.%s', $filename_no_ext, rand(0, 999), $filenameParts['extension'] );
|
338 |
+
} while( file_exists($upload_path . $filename ) );
|
339 |
+
}
|
340 |
+
|
341 |
+
// Check the image...
|
342 |
+
$ImageData = getimagesize($temp);
|
343 |
+
if( $ImageData && ( $ImageData[2] == IMAGETYPE_JPEG || $ImageData[2] == IMAGETYPE_PNG ) && $ImageData[0] == $ImageData[1] ) // Just check that it is an image, the correct image type and that the image is square
|
344 |
+
{
|
345 |
+
move_uploaded_file($temp, $upload_path . $filename);
|
346 |
+
$Feed['itunes_image'] = $urlImages . $filename;
|
347 |
+
}
|
348 |
+
else
|
349 |
+
{
|
350 |
+
echo '<div class="powerpress-error">Invalid iTunes image: ' . htmlspecialchars($_FILES['itunes_image_file']['name']) . '</div>';
|
351 |
+
}
|
352 |
+
}
|
353 |
+
|
354 |
+
// New RSS2 image
|
355 |
+
if( @$_POST['rss2_image_checkbox'] == 1 )
|
356 |
+
{
|
357 |
+
$filename = str_replace(" ", "_", basename($_FILES['rss2_image_file']['name']) );
|
358 |
+
$temp = $_FILES['rss2_image_file']['tmp_name'];
|
359 |
+
|
360 |
+
if( file_exists($upload_path . $filename ) )
|
361 |
+
{
|
362 |
+
$filenameParts = pathinfo($filename);
|
363 |
+
do {
|
364 |
+
$filename_no_ext = substr($filenameParts['basename'], 0, (strlen($filenameParts['extension'])+1) * -1 );
|
365 |
+
$filename = sprintf('%s-%03d.%s', $filename_no_ext, rand(0, 999), $filenameParts['extension'] );
|
366 |
+
} while( file_exists($upload_path . $filename ) );
|
367 |
+
}
|
368 |
+
|
369 |
+
if( getimagesize($temp) ) // Just check that it is an image, we may add more to this later
|
370 |
+
{
|
371 |
+
move_uploaded_file($temp, $upload_path . $filename);
|
372 |
+
$Feed['rss2_image'] = $urlImages . $filename;
|
373 |
+
}
|
374 |
+
else
|
375 |
+
{
|
376 |
+
echo '<div class="powerpress-error">Invalid RSS image: ' . htmlspecialchars($_FILES['rss2_image_file']['name']) . '</div>';
|
377 |
+
}
|
378 |
+
}
|
379 |
+
|
380 |
+
// Wordpress adds slashes to everything, but since we're storing everything serialized, lets remove them...
|
381 |
+
while( list($key,$value) = each($General) )
|
382 |
+
$General[$key] = stripslashes($value);
|
383 |
+
reset($General);
|
384 |
+
while( list($key,$value) = each($Feed) )
|
385 |
+
$Feed[$key] = stripslashes($value);
|
386 |
+
reset($Feed);
|
387 |
+
|
388 |
+
// Update the settings in the database:
|
389 |
+
update_option( 'powerpress_general', $General);
|
390 |
+
update_option( 'powerpress_feed', $Feed );
|
391 |
+
|
392 |
+
?>
|
393 |
+
<div class="updated powerpress-notice"><?php _e('Blubrry Powerpress settings saved.'); ?></div>
|
394 |
+
<?php
|
395 |
+
|
396 |
+
if( @$_POST['TestiTunesPing'] == 1 )
|
397 |
+
{
|
398 |
+
$PingResults = powerpress_ping_itunes($General['itunes_url']);
|
399 |
+
if( @$PingResults['success'] )
|
400 |
+
{
|
401 |
+
?>
|
402 |
+
<div class="updated powerpress-notice">iTunes Ping Successful. Podcast Feed URL: <?php echo $PingResults['feed_url']; ?>
|
403 |
+
</div>
|
404 |
+
<?php
|
405 |
+
}
|
406 |
+
else
|
407 |
+
{
|
408 |
+
echo '<div class="powerpress-error">' . htmlspecialchars($PingResults['content']) . '</div>';
|
409 |
+
}
|
410 |
+
}
|
411 |
+
|
412 |
+
}
|
413 |
+
|
414 |
+
// Get the general settings
|
415 |
+
$General = get_option('powerpress_general');
|
416 |
+
|
417 |
+
// Get previous podpress settings if no general settings set
|
418 |
+
if( !$General )
|
419 |
+
$PodpressData = get_option('podPress_config');
|
420 |
+
|
421 |
+
if( !$General ) // If no general settings, lets pre-populate or copy from podpress
|
422 |
+
{
|
423 |
+
$General = array();
|
424 |
+
$General['process_podpress'] = 1;
|
425 |
+
$General['display_player'] = 1;
|
426 |
+
$General['player_function'] = 1;
|
427 |
+
$General['podcast_link'] = 1;
|
428 |
+
$General['ping_itunes'] = 1;
|
429 |
+
$PodpressData = get_option('podPress_config');
|
430 |
+
if( $PodpressData ) // If no general settings, lets set defaults or copy from podpress.
|
431 |
+
{
|
432 |
+
?>
|
433 |
+
<div class="updated powerpress-notice"><?php _e('Podpress settings detected. Please click \'Save Changes\' to apply detected settings.'); ?></div>
|
434 |
+
<?php
|
435 |
+
// Lets try to copy settings from podpress
|
436 |
+
$General['default_url'] = $PodpressData['mediaWebPath'];
|
437 |
+
if( substr($General['default_url'], 0, -1) != '/' )
|
438 |
+
$General['default_url'] .= '/'; // Add the trailing slash, donno it's not there...
|
439 |
+
|
440 |
+
// Insert the blubrry redirect
|
441 |
+
if( isset($PodpressData['statBluBrryProgramKeyword']) )
|
442 |
+
{
|
443 |
+
$General['redirect1'] = 'http://media.blubrry.com/'.$PodpressData['statBluBrryProgramKeyword'].'/';
|
444 |
+
}
|
445 |
+
|
446 |
+
// Insert the Podtrac redirect
|
447 |
+
if( $PodpressData['enable3rdPartyStats'] == 'PodTrac' )
|
448 |
+
{
|
449 |
+
if( $General['redirect1'] )
|
450 |
+
$General['redirect2'] = 'http://www.podtrac.com/pts/redirect.mp3/';
|
451 |
+
else
|
452 |
+
$General['redirect1'] = 'http://www.podtrac.com/pts/redirect.mp3/';
|
453 |
+
}
|
454 |
+
|
455 |
+
if( $PodpressData['contentDownload'] == 'enabled' )
|
456 |
+
$General['podcast_link'] = 1;
|
457 |
+
else
|
458 |
+
$General['podcast_link'] = 0;
|
459 |
+
|
460 |
+
if( $PodpressData['contentPlayer'] == 'both' )
|
461 |
+
$General['player_function'] = 1;
|
462 |
+
else if( $PodpressData['contentPlayer'] == 'inline' )
|
463 |
+
$General['player_function'] = 2;
|
464 |
+
else if( $PodpressData['contentPlayer'] == 'popup' )
|
465 |
+
$General['player_function'] = 3;
|
466 |
+
else
|
467 |
+
$General['player_function'] = 0;
|
468 |
+
|
469 |
+
if( $PodpressData['contentPlayer'] == 'start' )
|
470 |
+
$General['display_player'] = 2;
|
471 |
+
else
|
472 |
+
$General['display_player'] = 1;
|
473 |
+
|
474 |
+
$General['itunes_url'] = 'http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id='. $PodpressData['iTunes']['FeedID'];
|
475 |
+
}
|
476 |
+
}
|
477 |
+
// Format the data for printing in html
|
478 |
+
while( list($key,$value) = each($General) )
|
479 |
+
$General[$key] = htmlspecialchars($value);
|
480 |
+
reset($General);
|
481 |
+
|
482 |
+
// Load feed settings
|
483 |
+
$FeedSettings = get_option('powerpress_feed');
|
484 |
+
|
485 |
+
if( !$FeedSettings ) // If no feed settings, lets set defaults or copy from podpress.
|
486 |
+
{
|
487 |
+
$FeedSettings = array();
|
488 |
+
$FeedSettings['apply_to'] = 1; // Default, apply to all the rss2 feeds
|
489 |
+
|
490 |
+
if( $PodpressData )
|
491 |
+
{
|
492 |
+
$FeedSettings['itunes_image'] = $PodpressData['iTunes']['image'];
|
493 |
+
if( strstr($FeedSettings['itunes_image'], 'powered_by_podpress') )
|
494 |
+
$FeedSettings['itunes_image'] = ''; // We're not using podpress anymore
|
495 |
+
|
496 |
+
$FeedSettings['itunes_summary'] = $PodpressData['iTunes']['summary'];
|
497 |
+
$FeedSettings['itunes_talent_name'] = $PodpressData['iTunes']['author'];
|
498 |
+
$FeedSettings['itunes_subtitle'] = $PodpressData['iTunes']['subtitle'];
|
499 |
+
$FeedSettings['itunes_keywords'] = $PodpressData['iTunes']['keywords'];
|
500 |
+
$FeedSettings['copyright'] = $PodpressData['rss_copyright'];
|
501 |
+
// Categories are tricky...
|
502 |
+
$iTunesCategories = powerpress_itunes_categories(true);
|
503 |
+
for( $x = 0; $x < 3; $x++ )
|
504 |
+
{
|
505 |
+
$CatDesc = str_replace(':', ' > ', $PodpressData['iTunes']['category'][$x]);
|
506 |
+
$CatKey = array_search($CatDesc, $iTunesCategories);
|
507 |
+
if( $CatKey )
|
508 |
+
$FeedSettings['itunes_cat_'.($x+1)] = $CatKey;
|
509 |
+
}
|
510 |
+
|
511 |
+
if( $PodpressData['iTunes']['explicit'] == 'No' )
|
512 |
+
$FeedSettings['itunes_explicit'] = 0;
|
513 |
+
else if( $PodpressData['iTunes']['explicit'] == 'Yes' )
|
514 |
+
$FeedSettings['itunes_explicit'] = 1;
|
515 |
+
else if( $PodpressData['iTunes']['explicit'] == 'Clean' )
|
516 |
+
$FeedSettings['itunes_explicit'] = 2;
|
517 |
+
}
|
518 |
+
|
519 |
+
// Lastly, lets try to get the RSS image from the database
|
520 |
+
$RSSImage = get_option('rss_image');
|
521 |
+
if( $RSSImage )
|
522 |
+
$FeedSettings['rss2_image'] = $RSSImage;
|
523 |
+
if( strstr($FeedSettings['rss2_image'], 'powered_by_podpress') )
|
524 |
+
$FeedSettings['rss2_image'] = ''; // We're not using podpress anymore
|
525 |
+
$AdminEmail = get_option('admin_email');
|
526 |
+
if( $AdminEmail )
|
527 |
+
$FeedSettings['email'] = $AdminEmail;
|
528 |
+
|
529 |
+
//var_dump($FeedSettings);
|
530 |
+
//var_dump($PodpressData);
|
531 |
+
//exit;
|
532 |
+
}
|
533 |
+
// Format the data for printing in html
|
534 |
+
while( list($key,$value) = each($FeedSettings) )
|
535 |
+
$FeedSettings[$key] = htmlspecialchars($value);
|
536 |
+
reset($FeedSettings);
|
537 |
+
|
538 |
+
// Now display the options editing screen
|
539 |
+
|
540 |
+
echo '<div class="wrap">';
|
541 |
+
|
542 |
+
// Start the form
|
543 |
+
?>
|
544 |
+
|
545 |
+
|
546 |
+
<form enctype="multipart/form-data" method="post" action="<?php echo str_replace( '%7E', '~', $_SERVER['REQUEST_URI']); ?>">
|
547 |
+
|
548 |
+
|
549 |
+
<?php wp_nonce_field('update-options'); ?>
|
550 |
+
|
551 |
+
<h2><?php _e("Basic Settings"); ?></h2>
|
552 |
+
|
553 |
+
<table class="form-table">
|
554 |
+
<tr valign="top">
|
555 |
+
<th scope="row"><?php _e("Default Media URL"); ?></th>
|
556 |
+
<td>
|
557 |
+
<input type="text" style="width: 80%;" name="General[default_url]" value="<?php echo $General['default_url']; ?>" maxlength="250" />
|
558 |
+
<p>URL above will prefix entered file names that do not start with 'http://'. URL above must end with a trailing slash.
|
559 |
+
You may leave blank if you always enter the complete URL to your media when creating podcast episodes.
|
560 |
+
</p>
|
561 |
+
<p>e.g. http://example.com/mediafolder/</p>
|
562 |
+
</td>
|
563 |
+
</tr>
|
564 |
+
|
565 |
+
<tr valign="top">
|
566 |
+
<th scope="row">
|
567 |
+
|
568 |
+
<?php _e("Podpress Episodes"); ?></th>
|
569 |
+
<td>
|
570 |
+
<select name="General[process_podpress]">
|
571 |
+
<?php
|
572 |
+
$options = array(0=>'Ignore', 1=>'Include in Posts and Feeds');
|
573 |
+
|
574 |
+
while( list($value,$desc) = each($options) )
|
575 |
+
echo "\t<option value=\"$value\"". ($General['process_podpress']==$value?' selected':''). ">$desc</option>\n";
|
576 |
+
|
577 |
+
?>
|
578 |
+
</select> (includes podcast episodes previously created in Podpress)
|
579 |
+
</td>
|
580 |
+
</tr>
|
581 |
+
|
582 |
+
<tr valign="top">
|
583 |
+
<th scope="row"><?php _e("iTunes URL"); ?></th>
|
584 |
+
<td>
|
585 |
+
<input type="text" style="width: 80%;" name="General[itunes_url]" value="<?php echo $General['itunes_url']; ?>" maxlength="250" />
|
586 |
+
<p>Click the following link to <a href="https://phobos.apple.com/WebObjects/MZFinance.woa/wa/publishPodcast" target="_blank" title="Publish a Podcast on iTunes">Publish a Podcast on iTunes</a>.
|
587 |
+
Once your podcast is listed on iTunes, enter your one click subscription URL above.
|
588 |
+
</p>
|
589 |
+
<p>e.g. http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=000000000</p>
|
590 |
+
</td>
|
591 |
+
</tr>
|
592 |
+
|
593 |
+
<?php
|
594 |
+
$OpenSSLSupport = extension_loaded('openssl');
|
595 |
+
?>
|
596 |
+
<tr valign="top">
|
597 |
+
<th scope="row">
|
598 |
+
|
599 |
+
<?php _e("Ping iTunes"); ?></th>
|
600 |
+
<td>
|
601 |
+
<select name="General[ping_itunes]"<?php if( $OpenSSLSupport == false ) echo ' disabled'; ?>>
|
602 |
+
<?php
|
603 |
+
$options = array(0=>'No ', 1=>'Yes ');
|
604 |
+
|
605 |
+
if( $OpenSSLSupport == false )
|
606 |
+
$value = 0;
|
607 |
+
|
608 |
+
while( list($value,$desc) = each($options) )
|
609 |
+
echo "\t<option value=\"$value\"". ($General['ping_itunes']==$value?' selected':''). ">$desc</option>\n";
|
610 |
+
|
611 |
+
?>
|
612 |
+
</select> (Notify iTunes when you publish a new episode.)
|
613 |
+
<p><input name="TestiTunesPing" type="checkbox" value="1"<?php if( $OpenSSLSupport == false ) echo ' disabled'; ?> /> Test iTunes Ping (recommended)</p>
|
614 |
+
</td>
|
615 |
+
</tr>
|
616 |
+
|
617 |
+
</table>
|
618 |
+
<?php if( $OpenSSLSupport == false ) { ?>
|
619 |
+
<div class="powerpress-error">Ping iTunes requires OpenSSL in PHP. Please refer to your php.ini to enable the php_openssl module.</div>
|
620 |
+
<?php } ?>
|
621 |
+
<br />
|
622 |
+
|
623 |
+
|
624 |
+
<h2><?php _e("Presentation Settings"); ?></h2>
|
625 |
+
|
626 |
+
<p style="margin-bottom: 0;">Configure how your media will be found on your blog.</p>
|
627 |
+
|
628 |
+
|
629 |
+
<table class="form-table">
|
630 |
+
<tr valign="top">
|
631 |
+
<th scope="row"><?php _e("Display Player"); ?></th>
|
632 |
+
<td><select name="General[display_player]">
|
633 |
+
<?php
|
634 |
+
$displayoptions = array(1=>"Below Post", 2=>"Above Post", 0=>"None");
|
635 |
+
|
636 |
+
while( list($value,$desc) = each($displayoptions) )
|
637 |
+
echo "\t<option value=\"$value\"". ($General['display_player']==$value?' selected':''). ">$desc</option>\n";
|
638 |
+
|
639 |
+
?>
|
640 |
+
</select>
|
641 |
+
</td>
|
642 |
+
</tr>
|
643 |
+
|
644 |
+
<tr valign="top">
|
645 |
+
<th scope="row">
|
646 |
+
<?php _e("Player Function"); ?></th>
|
647 |
+
<td><select name="General[player_function]">
|
648 |
+
<?php
|
649 |
+
$playeroptions = array(1=>'On Page & New Window', 2=>'On Page Only', 3=>'New Window Only', 0=>'Disable');
|
650 |
+
|
651 |
+
while( list($value,$desc) = each($playeroptions) )
|
652 |
+
echo "\t<option value=\"$value\"". ($General['player_function']==$value?' selected':''). ">".htmlspecialchars($desc)."</option>\n";
|
653 |
+
|
654 |
+
?>
|
655 |
+
</select>
|
656 |
+
</td>
|
657 |
+
</tr>
|
658 |
+
|
659 |
+
<tr valign="top">
|
660 |
+
<th scope="row">
|
661 |
+
|
662 |
+
<?php _e("Download Link"); ?></th>
|
663 |
+
<td>
|
664 |
+
<select name="General[podcast_link]">
|
665 |
+
<?php
|
666 |
+
$linkoptions = array(1=>"Display", 0=>"Disable");
|
667 |
+
|
668 |
+
while( list($value,$desc) = each($linkoptions) )
|
669 |
+
echo "\t<option value=\"$value\"". ($General['podcast_link']==$value?' selected':''). ">$desc</option>\n";
|
670 |
+
|
671 |
+
?>
|
672 |
+
</select>
|
673 |
+
</td>
|
674 |
+
</tr>
|
675 |
+
</table>
|
676 |
+
|
677 |
+
<br />
|
678 |
+
<h2><?php _e("Media Statistics"); ?></h2>
|
679 |
+
<p style="margin-bottom: 0;">Configure 3rd party statistics services to measure your media. (optional)</p>
|
680 |
+
|
681 |
+
<table class="form-table">
|
682 |
+
<tr valign="top">
|
683 |
+
<th scope="row">
|
684 |
+
<?php _e("Redirect URL 1"); ?>
|
685 |
+
</th>
|
686 |
+
<td>
|
687 |
+
<input type="text" style="width: 60%;" name="General[redirect1]" value="<?php echo $General['redirect1']; ?>" maxlength="250" />
|
688 |
+
</td>
|
689 |
+
</tr>
|
690 |
+
|
691 |
+
<tr valign="top">
|
692 |
+
<th scope="row">
|
693 |
+
<?php _e("Redirect URL 2"); ?>
|
694 |
+
</th>
|
695 |
+
<td>
|
696 |
+
<input type="text" style="width: 60%;" name="General[redirect2]" value="<?php echo $General['redirect2']; ?>" maxlength="250" />
|
697 |
+
</td>
|
698 |
+
</tr>
|
699 |
+
|
700 |
+
<tr valign="top">
|
701 |
+
<th scope="row">
|
702 |
+
<?php _e("Redirect URL 3"); ?>
|
703 |
+
</th>
|
704 |
+
<td>
|
705 |
+
<input type="text" style="width: 60%;" name="General[redirect3]" value="<?php echo $General['redirect3']; ?>" maxlength="250" />
|
706 |
+
</td>
|
707 |
+
</tr>
|
708 |
+
</table>
|
709 |
+
<p>
|
710 |
+
The services above must support redirects that do
|
711 |
+
not include nested 'http://' within the URL. Statistics services such as
|
712 |
+
<a href="http://www.podtrac.com" target="_blank" title="PodTrac">PodTrac.com</a>,
|
713 |
+
<a href="http://www.blubrry.com/podcast_statistics/" target="_blank" title="Blubrry Statistics">Blubrry.com</a>,
|
714 |
+
<a href="http://www.techpodcasts.com/podcast_statistics/" target="_blank" title="TechPodcasts Statistics">TechPodcasts.com</a>,
|
715 |
+
<a href="http://www.rawvoice.com/products/statistics/" target="_blank" title="RawVoice Statistics">RawVoice.com</a>
|
716 |
+
are supported.
|
717 |
+
</p>
|
718 |
+
<br />
|
719 |
+
<h2><?php _e("Feed Settings"); ?></h2>
|
720 |
+
<p style="margin-bottom: 0;">
|
721 |
+
Configure your feeds to support podcasting.
|
722 |
+
</p>
|
723 |
+
<table class="form-table">
|
724 |
+
|
725 |
+
<tr valign="top">
|
726 |
+
<th scope="row">
|
727 |
+
|
728 |
+
<?php _e("Apply Settings To"); ?></th>
|
729 |
+
<td>
|
730 |
+
<select name="Feed[apply_to]">
|
731 |
+
<?php
|
732 |
+
$applyoptions = array(1=>'All RSS2 Feeds', 2=>'Main RSS2 Feed only', 0=>'Disable (settings below ignored)');
|
733 |
+
|
734 |
+
while( list($value,$desc) = each($applyoptions) )
|
735 |
+
echo "\t<option value=\"$value\"". ($FeedSettings['apply_to']==$value?' selected':''). ">$desc</option>\n";
|
736 |
+
|
737 |
+
?>
|
738 |
+
</select>
|
739 |
+
<p>Select 'All RSS Feeds' to include podcast episodes in all feeds such as category and tag feeds.</p>
|
740 |
+
<p>Select 'Main RSS2 Feed only' to include podcast episodes only in your primary RSS2 feed.</p>
|
741 |
+
<p>Select 'Disable' to prevent Blubrry Powerpress from adding podcast episodes to any feeds.</p>
|
742 |
+
</td>
|
743 |
+
</tr>
|
744 |
+
|
745 |
+
<tr valign="top">
|
746 |
+
<th scope="row">
|
747 |
+
|
748 |
+
<?php _e("iTunes Summary"); ?></th>
|
749 |
+
<td>
|
750 |
+
<p>Your summary may not contain HTML and cannot exceed 4,000 characters in length.</p>
|
751 |
+
|
752 |
+
<textarea name="Feed[itunes_summary]" rows="5" style="width:80%;" ><?php echo $FeedSettings['itunes_summary']; ?></textarea>
|
753 |
+
</td>
|
754 |
+
</tr>
|
755 |
+
|
756 |
+
<tr valign="top">
|
757 |
+
<th scope="row">
|
758 |
+
<?php _e("iTunes Program Subtitle"); ?> <br />
|
759 |
+
</th>
|
760 |
+
<td>
|
761 |
+
<input type="text" name="Feed[itunes_subtitle]"style="width: 60%;" value="<?php echo $FeedSettings['itunes_subtitle']; ?>" maxlength="250" />
|
762 |
+
</td>
|
763 |
+
</tr>
|
764 |
+
|
765 |
+
<tr valign="top">
|
766 |
+
<th scope="row">
|
767 |
+
<?php _e("iTunes Program Keywords"); ?> <br />
|
768 |
+
</th>
|
769 |
+
<td>
|
770 |
+
<input type="text" name="Feed[itunes_keywords]"style="width: 60%;" value="<?php echo $FeedSettings['itunes_keywords']; ?>" maxlength="250" />
|
771 |
+
<p>Enter up to 12 keywords separated by commas.</p>
|
772 |
+
</td>
|
773 |
+
</tr>
|
774 |
+
|
775 |
+
<tr valign="top">
|
776 |
+
<th scope="row">
|
777 |
+
<?php _e("iTunes Category 1"); ?>
|
778 |
+
</th>
|
779 |
+
<td>
|
780 |
+
<select name="Feed[itunes_cat_1]">
|
781 |
+
<?php
|
782 |
+
$linkoptions = array("On page", "Disable");
|
783 |
+
|
784 |
+
$Categories = powerpress_itunes_categories(true);
|
785 |
+
|
786 |
+
echo '<option value="">Select Category</option>';
|
787 |
+
|
788 |
+
while( list($value,$desc) = each($Categories) )
|
789 |
+
echo "\t<option value=\"$value\"". ($FeedSettings['itunes_cat_1']==$value?' selected':''). ">".htmlspecialchars($desc)."</option>\n";
|
790 |
+
|
791 |
+
reset($Categories);
|
792 |
+
?>
|
793 |
+
</select>
|
794 |
+
</td>
|
795 |
+
</tr>
|
796 |
+
|
797 |
+
<tr valign="top">
|
798 |
+
<th scope="row">
|
799 |
+
<?php _e("iTunes Category 2"); ?>
|
800 |
+
</th>
|
801 |
+
<td>
|
802 |
+
<select name="Feed[itunes_cat_2]">
|
803 |
+
<?php
|
804 |
+
$linkoptions = array("On page", "Disable");
|
805 |
+
|
806 |
+
echo '<option value="">Select Category</option>';
|
807 |
+
|
808 |
+
while( list($value,$desc) = each($Categories) )
|
809 |
+
echo "\t<option value=\"$value\"". ($FeedSettings['itunes_cat_2']==$value?' selected':''). ">".htmlspecialchars($desc)."</option>\n";
|
810 |
+
|
811 |
+
reset($Categories);
|
812 |
+
|
813 |
+
?>
|
814 |
+
</select>
|
815 |
+
</td>
|
816 |
+
</tr>
|
817 |
+
|
818 |
+
<tr valign="top">
|
819 |
+
<th scope="row">
|
820 |
+
<?php _e("iTunes Category 3"); ?>
|
821 |
+
</th>
|
822 |
+
<td>
|
823 |
+
<select name="Feed[itunes_cat_3]">
|
824 |
+
<?php
|
825 |
+
$linkoptions = array("On page", "Disable");
|
826 |
+
|
827 |
+
echo '<option value="">Select Category</option>';
|
828 |
+
|
829 |
+
while( list($value,$desc) = each($Categories) )
|
830 |
+
echo "\t<option value=\"$value\"". ($FeedSettings['itunes_cat_3']==$value?' selected':''). ">".htmlspecialchars($desc)."</option>\n";
|
831 |
+
|
832 |
+
reset($Categories);
|
833 |
+
?>
|
834 |
+
</select>
|
835 |
+
</td>
|
836 |
+
</tr>
|
837 |
+
|
838 |
+
<tr valign="top">
|
839 |
+
<th scope="row">
|
840 |
+
<?php _e("iTunes Explicit"); ?>
|
841 |
+
</th>
|
842 |
+
<td>
|
843 |
+
<select name="Feed[itunes_explicit]">
|
844 |
+
<?php
|
845 |
+
$explicit = array(0=>"no - display nothing", 1=>"yes - explicit content", 2=>"clean - no explicit content");
|
846 |
+
|
847 |
+
while( list($value,$desc) = each($explicit) )
|
848 |
+
echo "\t<option value=\"$value\"". ($FeedSettings['itunes_explicit']==$value?' selected':''). ">$desc</option>\n";
|
849 |
+
|
850 |
+
?>
|
851 |
+
</select>
|
852 |
+
</td>
|
853 |
+
</tr>
|
854 |
+
|
855 |
+
<tr valign="top">
|
856 |
+
<th scope="row">
|
857 |
+
<?php _e("iTunes Image"); ?>
|
858 |
+
</th>
|
859 |
+
<td>
|
860 |
+
<input type="text" id="itunes_image" name="Feed[itunes_image]" style="width: 60%;" value="<?php echo $FeedSettings['itunes_image']; ?>" maxlength="250" />
|
861 |
+
<a href="#" onclick="javascript: window.open( document.getElementById('itunes_image').value ); return false;">preview</a>
|
862 |
+
|
863 |
+
<p>Put the URL to the iTunes image above. e.g. http://mysite.com/images/itunes.jpg<br /><br />iTunes prefers square .jpg or .png images that are at 600 x 600 pixels (prevously 300 x 300), which is different than what is specified for the standard RSS image.</p>
|
864 |
+
|
865 |
+
<?php if( $SupportUploads ) { ?>
|
866 |
+
<p><input name="itunes_image_checkbox" type="checkbox" onchange="powerpress_show_field('itunes_image_upload', this.checked)" value="1" /> Upload new image: </p>
|
867 |
+
<div style="display:none" id="itunes_image_upload">
|
868 |
+
<label for="itunes_image">Choose file:</label><input type="file" name="itunes_image_file" />
|
869 |
+
</div>
|
870 |
+
<?php } ?>
|
871 |
+
</td>
|
872 |
+
</tr>
|
873 |
+
|
874 |
+
<tr valign="top">
|
875 |
+
<th scope="row">
|
876 |
+
<?php _e("RSS2 Image"); ?> <br />
|
877 |
+
</th>
|
878 |
+
<td>
|
879 |
+
<input type="text" id="rss2_image" name="Feed[rss2_image]" style="width: 60%;" value="<?php echo $FeedSettings['rss2_image']; ?>" maxlength="250" />
|
880 |
+
<a href="#" onclick="javascript: window.open( document.getElementById('rss2_image').value ); return false;">preview</a>
|
881 |
+
|
882 |
+
<p>Put the URL to the RSS image above. e.g. http://mysite.com/images/rss.jpg</p>
|
883 |
+
<p>RSS image should be at least 88 and at most 144 pixels wide and at least 31 and at most 400 pixels high in either .gif, .jpg and .png format. A square 144 x 144 pixel image is recommended.</p>
|
884 |
+
|
885 |
+
<?php if( $SupportUploads ) { ?>
|
886 |
+
<p><input name="rss2_image_checkbox" type="checkbox" onchange="powerpress_show_field('rss_image_upload', this.checked)" value="1" /> Upload new image</p>
|
887 |
+
<div style="display:none" id="rss_image_upload">
|
888 |
+
<label for="rss2_image">Choose file:</label><input type="file" name="rss2_image_file" />
|
889 |
+
</div>
|
890 |
+
<?php } ?>
|
891 |
+
</td>
|
892 |
+
</tr>
|
893 |
+
|
894 |
+
<tr valign="top">
|
895 |
+
<th scope="row">
|
896 |
+
<?php _e("Talent Name"); ?> <br />
|
897 |
+
</th>
|
898 |
+
<td>
|
899 |
+
<input type="text" name="Feed[itunes_talent_name]"style="width: 60%;" value="<?php echo $FeedSettings['itunes_talent_name']; ?>" maxlength="250" />
|
900 |
+
</td>
|
901 |
+
</tr>
|
902 |
+
|
903 |
+
<tr valign="top">
|
904 |
+
<th scope="row">
|
905 |
+
<?php _e("Email"); ?>
|
906 |
+
</th>
|
907 |
+
<td>
|
908 |
+
<input type="text" name="Feed[email]" style="width: 60%;" value="<?php echo $FeedSettings['email']; ?>" maxlength="250" />
|
909 |
+
</td>
|
910 |
+
</tr>
|
911 |
+
|
912 |
+
<tr valign="top">
|
913 |
+
<th scope="row">
|
914 |
+
<?php _e("Copyright"); ?>
|
915 |
+
</th>
|
916 |
+
<td>
|
917 |
+
<input type="text" name="Feed[copyright]" style="width: 60%;" value="<?php echo $FeedSettings['copyright']; ?>" maxlength="250" />
|
918 |
+
</td>
|
919 |
+
</tr>
|
920 |
+
</table>
|
921 |
+
<p style="font-size: 85%; text-align: center;">
|
922 |
+
<a href="http://www.blubrry.com/powerpress/" title="Blubrry Powerpress" target="_blank">Blubrry Powerpress</a> <?php echo POWERPRESS_VERSION; ?>
|
923 |
+
</p>
|
924 |
+
<p class="submit">
|
925 |
+
<input type="submit" name="Submit" value="<?php _e('Save Changes' ) ?>" />
|
926 |
+
</p>
|
927 |
+
|
928 |
+
</form>
|
929 |
+
</div>
|
930 |
+
<hr />
|
931 |
+
|
932 |
+
<?php
|
933 |
+
}
|
934 |
+
|
935 |
+
/*
|
936 |
+
// Helper functions:
|
937 |
+
*/
|
938 |
+
function powerpress_ping_itunes($iTunes_url)
|
939 |
+
{
|
940 |
+
if( strpos($iTunes_url, 'phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=' ) === false )
|
941 |
+
return array('error'=>true, 'content'=>'iTunes URL required to ping iTunes.');
|
942 |
+
|
943 |
+
// convert: https://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=
|
944 |
+
// to: https://phobos.apple.com/WebObjects/MZFinance.woa/wa/pingPodcast?id=
|
945 |
+
$ping_url = str_replace(
|
946 |
+
array( 'https://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=',
|
947 |
+
'http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=',
|
948 |
+
'https://www.itunes.com/podcast?id=',
|
949 |
+
'http://www.itunes.com/podcast?id='),
|
950 |
+
'https://phobos.apple.com/WebObjects/MZFinance.woa/wa/pingPodcast?id=', $iTunes_url);
|
951 |
+
|
952 |
+
$fp = fopen($ping_url, 'rb');
|
953 |
+
if( $fp )
|
954 |
+
{
|
955 |
+
$tempdata = '';
|
956 |
+
while( !feof($fp) )
|
957 |
+
$tempdata .= fread($fp, 8192);
|
958 |
+
fclose($fp);
|
959 |
+
if( stristr($tempdata, 'No Podcast Found') )
|
960 |
+
return array('error'=>true, 'content'=>'No Podcast Found from iTunes ping request');
|
961 |
+
|
962 |
+
// Parse the data into something readable
|
963 |
+
$results = trim( str_replace('Podcast Ping Received', '', strip_tags($tempdata) ) );
|
964 |
+
list($null, $FeedURL, $null, $null, $null, $PodcastID) = split("\n", $results );
|
965 |
+
|
966 |
+
return array('success'=>true, 'content'=>$tempdata, 'feed_url'=>trim($FeedURL), 'podcast_id'=>trim($PodcastID) );
|
967 |
+
}
|
968 |
+
return array('error'=>true, 'content'=>'Unable to connect to iTunes ping server.');
|
969 |
+
}
|
970 |
+
?>
|
readme.txt
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
=== Blubrry Powerpress Podcasting plugin ===
|
2 |
+
Contributors: Angelo Mandato, Blubrry.com
|
3 |
+
Tags: podcast, podcasting, itunes, enclosure, zune, iphone, audio, video, rss2, feed, player, media, rss
|
4 |
+
Requires at least: 2.5.0
|
5 |
+
Tested up to: 2.6.0
|
6 |
+
Stable tag: 0.2
|
7 |
+
|
8 |
+
Add podcasting support to your blog.
|
9 |
+
|
10 |
+
== Description ==
|
11 |
+
The Blubrry Powerpress Podcast Plugin has all of the essential features needed to provide podcasting support in a Wordpress blog.
|
12 |
+
|
13 |
+
The Blubrry Powerpress interface allows you to easily add/modify/remove podcast episodes from blog posts and includes a simple on-line media player, iTunes compatibile RSS feed tags, ability to upload cover art images, ping iTunes, detect media size, detect time duration (mp3's only) and add 3rd party media statistics.
|
14 |
+
|
15 |
+
Features:
|
16 |
+
|
17 |
+
* Easily add/modify/remove podcast episodes from blog posts
|
18 |
+
* Integrated media player
|
19 |
+
* iTunes RSS tags
|
20 |
+
* iTunes album/cover art
|
21 |
+
* upload new iTunes/RSS cover art
|
22 |
+
* Ping iTunes
|
23 |
+
* Media size detection
|
24 |
+
* Duration detection (mp3 only)
|
25 |
+
* 3rd party statistics integration
|
26 |
+
|
27 |
+
For the latest information visit the website.
|
28 |
+
|
29 |
+
http://www.blubrry.com/powerpress/
|
30 |
+
|
31 |
+
== Frequently Asked Questions ==
|
32 |
+
|
33 |
+
= Why doesn't Blubrry Powerpress support multiple enclosures? =
|
34 |
+
Blubrry Powerpress does not support multiple enclosures in one blog post. This is because each podcatcher handles multiple enclosures differently. iTunes will download the first enclosure that it sees in the feed ignoring the rest. Other podcatchers and podcasting directories either pick up the first enclosure or the last in each post item. This inconsistancy and combined with the fact that [Dave Winer does not recommend multiple enclosures](http://www.reallysimplesyndication.com/2004/12/21) is why the Blubrry Powerpress does not support them.
|
35 |
+
|
36 |
+
= Why doesn't Blubrry Powerpress include media statistics? =
|
37 |
+
Blubrry Powerpress does not include media statistics. This is not because Blubrry has its own statistics service, although that's a good reason by itself. Maintaining and calculating statistics is a resource and server intensive task that would add bloat to an otherwise lightweight Wordpress podcasting plugin. We recommend you use your media hosting's statistics and you're more than welcome to use the [Blubrry Statistics service](http://www.blubrry.com/podcast_statistics/) as well.
|
38 |
+
|
39 |
+
== Installation ==
|
40 |
+
1. Copy the entire directory from the downloaded zip file into the /wp-content/plugins/ folder.
|
41 |
+
2. Activate the "Blubrry Powerpress" plugin in the Plugin Management page.
|
42 |
+
3. Configure your Blubrry Powerpress by going to the **Settings** > **Blubrry Powerpress** page.
|
43 |
+
|
44 |
+
== Screenshots ==
|
45 |
+
1. Add podcast episode, found within the edit post screen
|
46 |
+
2. Cross section of Blubrry Powerpress settings page.
|
47 |
+
|
48 |
+
== Changelog ==
|
49 |
+
|
50 |
+
0.2 released on 08/11/2008
|
51 |
+
Initial release of Blubrry Powerpress
|
52 |
+
|
53 |
+
== Feedback ==
|
54 |
+
http://www.blubrry.com/powerpress/
|
rss_default.jpg
ADDED
Binary file
|
screenshot-1.jpg
ADDED
Binary file
|
screenshot-2.jpg
ADDED
Binary file
|