mirror of
https://github.com/Poniverse/Pony.fm.git
synced 2025-04-02 01:05:28 +02:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
a90cc8395c
154 changed files with 1185 additions and 2672 deletions
3
.git-crypt/.gitattributes
vendored
3
.git-crypt/.gitattributes
vendored
|
@ -1,3 +0,0 @@
|
||||||
# Do not edit this file. To specify the files to encrypt, create your own
|
|
||||||
# .gitattributes file in the directory where your files are.
|
|
||||||
* !filter !diff
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
3
.gitattributes
vendored
3
.gitattributes
vendored
|
@ -1,7 +1,4 @@
|
||||||
* text=auto
|
* text=auto
|
||||||
|
|
||||||
resources/environments/.env.stage filter=git-crypt diff=git-crypt
|
|
||||||
resources/environments/.env.production filter=git-crypt diff=git-crypt
|
|
||||||
|
|
||||||
*.css linguist-vendored
|
*.css linguist-vendored
|
||||||
*.less linguist-vendored
|
*.less linguist-vendored
|
||||||
|
|
4
Vagrantfile
vendored
4
Vagrantfile
vendored
|
@ -3,8 +3,8 @@ Vagrant.configure("2") do |config|
|
||||||
config.hostmanager.enabled = true
|
config.hostmanager.enabled = true
|
||||||
config.hostmanager.manage_host = true
|
config.hostmanager.manage_host = true
|
||||||
|
|
||||||
config.vm.box = 'laravel/homestead'
|
config.vm.box = 'laravel/homestead-7'
|
||||||
config.vm.box_version = '0.3.0'
|
config.vm.box_version = '0.2.0'
|
||||||
config.vm.provider "virtualbox" do |v|
|
config.vm.provider "virtualbox" do |v|
|
||||||
v.cpus = 4
|
v.cpus = 4
|
||||||
v.memory = 2048
|
v.memory = 2048
|
||||||
|
|
|
@ -28,7 +28,6 @@ use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||||
use Auth;
|
use Auth;
|
||||||
use Cache;
|
use Cache;
|
||||||
use Poniverse\Ponyfm\Traits\TrackCollection;
|
use Poniverse\Ponyfm\Traits\TrackCollection;
|
||||||
use URL;
|
|
||||||
use Poniverse\Ponyfm\Traits\SlugTrait;
|
use Poniverse\Ponyfm\Traits\SlugTrait;
|
||||||
use Venturecraft\Revisionable\RevisionableTrait;
|
use Venturecraft\Revisionable\RevisionableTrait;
|
||||||
|
|
||||||
|
@ -131,7 +130,7 @@ class Album extends Model
|
||||||
$data['description'] = $album->description;
|
$data['description'] = $album->description;
|
||||||
$data['is_downloadable'] = $is_downloadable;
|
$data['is_downloadable'] = $is_downloadable;
|
||||||
$data['share'] = [
|
$data['share'] = [
|
||||||
'url' => URL::to('/a' . $album->id),
|
'url' => action('AlbumsController@getShortlink', ['id' => $album->id]),
|
||||||
'tumblrUrl' => 'http://www.tumblr.com/share/link?url=' . urlencode($album->url) . '&name=' . urlencode($album->title) . '&description=' . urlencode($album->description),
|
'tumblrUrl' => 'http://www.tumblr.com/share/link?url=' . urlencode($album->url) . '&name=' . urlencode($album->title) . '&description=' . urlencode($album->description),
|
||||||
'twitterUrl' => 'https://platform.twitter.com/widgets/tweet_button.html?text=' . $album->title . ' by ' . $album->user->display_name . ' on Pony.fm'
|
'twitterUrl' => 'https://platform.twitter.com/widgets/tweet_button.html?text=' . $album->title . ' by ' . $album->user->display_name . ' on Pony.fm'
|
||||||
];
|
];
|
||||||
|
@ -198,12 +197,12 @@ class Album extends Model
|
||||||
|
|
||||||
public function getUrlAttribute()
|
public function getUrlAttribute()
|
||||||
{
|
{
|
||||||
return URL::to('albums/' . $this->id . '-' . $this->slug);
|
return action('AlbumsController@getShow', ['id' => $this->id, 'slug' => $this->slug]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDownloadUrl($format)
|
public function getDownloadUrl($format)
|
||||||
{
|
{
|
||||||
return URL::to('a' . $this->id . '/dl.' . Track::$Formats[$format]['extension']);
|
return action('AlbumsController@getDownload', ['id' => $this->id, 'extension' => Track::$Formats[$format]['extension']]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFilesize($format)
|
public function getFilesize($format)
|
||||||
|
|
|
@ -24,11 +24,25 @@ use Illuminate\Validation\Validator;
|
||||||
|
|
||||||
class CommandResponse
|
class CommandResponse
|
||||||
{
|
{
|
||||||
public static function fail($validator)
|
/**
|
||||||
|
* @var Validator
|
||||||
|
*/
|
||||||
|
private $_validator;
|
||||||
|
private $_response;
|
||||||
|
private $_didFail;
|
||||||
|
|
||||||
|
public static function fail($validatorOrMessages)
|
||||||
{
|
{
|
||||||
$response = new CommandResponse();
|
$response = new CommandResponse();
|
||||||
$response->_didFail = true;
|
$response->_didFail = true;
|
||||||
$response->_validator = $validator;
|
|
||||||
|
if (is_array($validatorOrMessages)) {
|
||||||
|
$response->_messages = $validatorOrMessages;
|
||||||
|
$response->_validator = null;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$response->_validator = $validatorOrMessages;
|
||||||
|
}
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
@ -42,10 +56,6 @@ class CommandResponse
|
||||||
return $cmdResponse;
|
return $cmdResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
private $_validator;
|
|
||||||
private $_response;
|
|
||||||
private $_didFail;
|
|
||||||
|
|
||||||
private function __construct()
|
private function __construct()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -73,4 +83,14 @@ class CommandResponse
|
||||||
{
|
{
|
||||||
return $this->_validator;
|
return $this->_validator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getMessages()
|
||||||
|
{
|
||||||
|
if ($this->_validator !== null) {
|
||||||
|
return $this->_validator->messages()->getMessages();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return $this->_messages;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,17 +20,22 @@
|
||||||
|
|
||||||
namespace Poniverse\Ponyfm\Commands;
|
namespace Poniverse\Ponyfm\Commands;
|
||||||
|
|
||||||
|
use Config;
|
||||||
|
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||||
|
use Poniverse\Ponyfm\Exceptions\InvalidEncodeOptionsException;
|
||||||
|
use Poniverse\Ponyfm\Jobs\EncodeTrackFile;
|
||||||
use Poniverse\Ponyfm\Track;
|
use Poniverse\Ponyfm\Track;
|
||||||
use Poniverse\Ponyfm\TrackFile;
|
use Poniverse\Ponyfm\TrackFile;
|
||||||
use AudioCache;
|
use AudioCache;
|
||||||
use File;
|
use File;
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Symfony\Component\Process\Exception\ProcessFailedException;
|
use Storage;
|
||||||
use Symfony\Component\Process\Process;
|
|
||||||
|
|
||||||
class UploadTrackCommand extends CommandBase
|
class UploadTrackCommand extends CommandBase
|
||||||
{
|
{
|
||||||
|
use DispatchesJobs;
|
||||||
|
|
||||||
|
|
||||||
private $_allowLossy;
|
private $_allowLossy;
|
||||||
private $_allowShortTrack;
|
private $_allowShortTrack;
|
||||||
private $_losslessFormats = [
|
private $_losslessFormats = [
|
||||||
|
@ -68,6 +73,21 @@ class UploadTrackCommand extends CommandBase
|
||||||
$trackFile = \Input::file('track');
|
$trackFile = \Input::file('track');
|
||||||
$audio = \AudioCache::get($trackFile->getPathname());
|
$audio = \AudioCache::get($trackFile->getPathname());
|
||||||
|
|
||||||
|
|
||||||
|
$track = new Track();
|
||||||
|
$track->user_id = $user->id;
|
||||||
|
$track->title = pathinfo($trackFile->getClientOriginalName(), PATHINFO_FILENAME);
|
||||||
|
$track->duration = $audio->getDuration();
|
||||||
|
$track->is_listed = true;
|
||||||
|
|
||||||
|
$track->save();
|
||||||
|
$track->ensureDirectoryExists();
|
||||||
|
|
||||||
|
Storage::makeDirectory(Config::get('ponyfm.files_directory') . '/queued-tracks', 0755, false, true);
|
||||||
|
$trackFile = $trackFile->move(Config::get('ponyfm.files_directory').'/queued-tracks', $track->id);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$validator = \Validator::make(['track' => $trackFile], [
|
$validator = \Validator::make(['track' => $trackFile], [
|
||||||
'track' =>
|
'track' =>
|
||||||
'required|'
|
'required|'
|
||||||
|
@ -77,24 +97,13 @@ class UploadTrackCommand extends CommandBase
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($validator->fails()) {
|
if ($validator->fails()) {
|
||||||
|
$track->delete();
|
||||||
return CommandResponse::fail($validator);
|
return CommandResponse::fail($validator);
|
||||||
}
|
}
|
||||||
|
|
||||||
$track = new Track();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$track->user_id = $user->id;
|
|
||||||
$track->title = pathinfo($trackFile->getClientOriginalName(), PATHINFO_FILENAME);
|
|
||||||
$track->duration = $audio->getDuration();
|
|
||||||
$track->is_listed = true;
|
|
||||||
|
|
||||||
$track->save();
|
|
||||||
|
|
||||||
$destination = $track->getDirectory();
|
|
||||||
$track->ensureDirectoryExists();
|
|
||||||
|
|
||||||
$source = $trackFile->getPathname();
|
$source = $trackFile->getPathname();
|
||||||
$index = 0;
|
|
||||||
|
|
||||||
// Lossy uploads need to be identified and set as the master file
|
// Lossy uploads need to be identified and set as the master file
|
||||||
// without being re-encoded.
|
// without being re-encoded.
|
||||||
|
@ -113,6 +122,7 @@ class UploadTrackCommand extends CommandBase
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$validator->messages()->add('track', 'The track does not contain audio in a known lossy format.');
|
$validator->messages()->add('track', 'The track does not contain audio in a known lossy format.');
|
||||||
|
$track->delete();
|
||||||
return CommandResponse::fail($validator);
|
return CommandResponse::fail($validator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,6 +136,9 @@ class UploadTrackCommand extends CommandBase
|
||||||
File::copy($source, $trackFile->getFile());
|
File::copy($source, $trackFile->getFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$trackFiles = [];
|
||||||
|
|
||||||
foreach (Track::$Formats as $name => $format) {
|
foreach (Track::$Formats as $name => $format) {
|
||||||
// Don't bother with lossless transcodes of lossy uploads, and
|
// Don't bother with lossless transcodes of lossy uploads, and
|
||||||
// don't re-encode the lossy master.
|
// don't re-encode the lossy master.
|
||||||
|
@ -136,6 +149,7 @@ class UploadTrackCommand extends CommandBase
|
||||||
$trackFile = new TrackFile();
|
$trackFile = new TrackFile();
|
||||||
$trackFile->is_master = $name === 'FLAC' ? true : false;
|
$trackFile->is_master = $name === 'FLAC' ? true : false;
|
||||||
$trackFile->format = $name;
|
$trackFile->format = $name;
|
||||||
|
$trackFile->status = TrackFile::STATUS_PROCESSING;
|
||||||
|
|
||||||
if (in_array($name, Track::$CacheableFormats) && $trackFile->is_master == false) {
|
if (in_array($name, Track::$CacheableFormats) && $trackFile->is_master == false) {
|
||||||
$trackFile->is_cacheable = true;
|
$trackFile->is_cacheable = true;
|
||||||
|
@ -144,29 +158,21 @@ class UploadTrackCommand extends CommandBase
|
||||||
}
|
}
|
||||||
$track->trackFiles()->save($trackFile);
|
$track->trackFiles()->save($trackFile);
|
||||||
|
|
||||||
// Encode track file
|
// All TrackFile records we need are synchronously created
|
||||||
$target = $trackFile->getFile();
|
// before kicking off the encode jobs in order to avoid a race
|
||||||
|
// condition with the "temporary" source file getting deleted.
|
||||||
$command = $format['command'];
|
$trackFiles[] = $trackFile;
|
||||||
$command = str_replace('{$source}', '"' . $source . '"', $command);
|
|
||||||
$command = str_replace('{$target}', '"' . $target . '"', $command);
|
|
||||||
|
|
||||||
Log::info('Encoding ' . $track->id . ' into ' . $target);
|
|
||||||
$this->notify('Encoding ' . $name, $index / count(Track::$Formats) * 100);
|
|
||||||
|
|
||||||
$process = new Process($command);
|
|
||||||
$process->mustRun();
|
|
||||||
|
|
||||||
// Update file size for track file
|
|
||||||
$trackFile->updateFilesize();
|
|
||||||
|
|
||||||
// Delete track file if it is cacheable
|
|
||||||
if ($trackFile->is_cacheable == true) {
|
|
||||||
File::delete($trackFile->getFile());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$track->updateTags();
|
try {
|
||||||
|
foreach($trackFiles as $trackFile) {
|
||||||
|
$this->dispatch(new EncodeTrackFile($trackFile, false, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (InvalidEncodeOptionsException $e) {
|
||||||
|
$track->delete();
|
||||||
|
return CommandResponse::fail(['track' => [$e->getMessage()]]);
|
||||||
|
}
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$track->delete();
|
$track->delete();
|
||||||
|
|
|
@ -365,7 +365,7 @@ class ImportMLPMA extends Command
|
||||||
$result = $upload->execute();
|
$result = $upload->execute();
|
||||||
|
|
||||||
if ($result->didFail()) {
|
if ($result->didFail()) {
|
||||||
$this->error(json_encode($result->getValidator()->messages()->getMessages(), JSON_PRETTY_PRINT));
|
$this->error(json_encode($result->getMessages(), JSON_PRETTY_PRINT));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Save metadata.
|
// Save metadata.
|
||||||
|
|
|
@ -18,27 +18,8 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace Poniverse\Ponyfm\Http\Controllers;
|
namespace Poniverse\Ponyfm\Exceptions;
|
||||||
|
|
||||||
use Poniverse\Ponyfm\User;
|
use InvalidArgumentException;
|
||||||
use File;
|
|
||||||
use Illuminate\Support\Facades\App;
|
|
||||||
|
|
||||||
class UsersController extends Controller
|
class InvalidEncodeOptionsException extends InvalidArgumentException {}
|
||||||
{
|
|
||||||
public function getAvatar($id, $type)
|
|
||||||
{
|
|
||||||
$coverType = Cover::getCoverFromName($type);
|
|
||||||
|
|
||||||
if ($coverType == null) {
|
|
||||||
App::abort(404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$user = User::find($id);
|
|
||||||
if (!$user) {
|
|
||||||
App::abort(404);
|
|
||||||
}
|
|
||||||
|
|
||||||
return File::inline($user->getAvatarFile($coverType['id']), 'image/png', 'cover.png');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -25,7 +25,6 @@ use Illuminate\Database\Eloquent\Relations\Relation;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Poniverse\Ponyfm\Traits\SlugTrait;
|
use Poniverse\Ponyfm\Traits\SlugTrait;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use URL;
|
|
||||||
use Venturecraft\Revisionable\RevisionableTrait;
|
use Venturecraft\Revisionable\RevisionableTrait;
|
||||||
|
|
||||||
class Genre extends Model
|
class Genre extends Model
|
||||||
|
@ -75,6 +74,6 @@ class Genre extends Model
|
||||||
* @return string relative, Angular-friendly URL to this genre
|
* @return string relative, Angular-friendly URL to this genre
|
||||||
*/
|
*/
|
||||||
public function getUrlAttribute() {
|
public function getUrlAttribute() {
|
||||||
return URL::route('tracks.discover', ['filter' => "genres-{$this->id}"], false);
|
return route('tracks.discover', ['filter' => "genres-{$this->id}"], false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ use Cover;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Input;
|
use Illuminate\Support\Facades\Input;
|
||||||
use Illuminate\Support\Facades\Response;
|
use Illuminate\Support\Facades\Response;
|
||||||
|
use Poniverse\Ponyfm\TrackFile;
|
||||||
|
|
||||||
class TracksController extends ApiControllerBase
|
class TracksController extends ApiControllerBase
|
||||||
{
|
{
|
||||||
|
@ -40,7 +41,31 @@ class TracksController extends ApiControllerBase
|
||||||
{
|
{
|
||||||
session_write_close();
|
session_write_close();
|
||||||
|
|
||||||
return $this->execute(new UploadTrackCommand());
|
try {
|
||||||
|
return $this->execute(new UploadTrackCommand());
|
||||||
|
|
||||||
|
} catch (\InvalidEncodeOptions $e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUploadStatus($trackId)
|
||||||
|
{
|
||||||
|
// TODO: authorize this
|
||||||
|
|
||||||
|
$track = Track::findOrFail($trackId);
|
||||||
|
|
||||||
|
if ($track->status === Track::STATUS_PROCESSING){
|
||||||
|
return Response::json(['message' => 'Processing...'], 202);
|
||||||
|
|
||||||
|
} elseif ($track->status === Track::STATUS_COMPLETE) {
|
||||||
|
return Response::json(['message' => 'Processing complete!'], 201);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// something went wrong
|
||||||
|
return Response::json(['error' => 'Processing failed!'], 500);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function postDelete($id)
|
public function postDelete($id)
|
||||||
|
@ -101,7 +126,7 @@ class TracksController extends ApiControllerBase
|
||||||
// Return URL or begin encoding
|
// Return URL or begin encoding
|
||||||
if ($trackFile->expires_at != null && File::exists($trackFile->getFile())) {
|
if ($trackFile->expires_at != null && File::exists($trackFile->getFile())) {
|
||||||
$url = $track->getUrlFor($format);
|
$url = $track->getUrlFor($format);
|
||||||
} elseif ($trackFile->is_in_progress === true) {
|
} elseif ($trackFile->status === TrackFile::STATUS_PROCESSING) {
|
||||||
$url = null;
|
$url = null;
|
||||||
} else {
|
} else {
|
||||||
$this->dispatch(new EncodeTrackFile($trackFile, true));
|
$this->dispatch(new EncodeTrackFile($trackFile, true));
|
||||||
|
|
|
@ -35,7 +35,7 @@ abstract class ApiControllerBase extends Controller
|
||||||
if ($result->didFail()) {
|
if ($result->didFail()) {
|
||||||
return Response::json([
|
return Response::json([
|
||||||
'message' => 'Validation failed',
|
'message' => 'Validation failed',
|
||||||
'errors' => $result->getValidator()->messages()->getMessages()
|
'errors' => $result->getMessages()
|
||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@ use DB;
|
||||||
use Input;
|
use Input;
|
||||||
use Poniverse;
|
use Poniverse;
|
||||||
use Redirect;
|
use Redirect;
|
||||||
use URL;
|
|
||||||
|
|
||||||
class AuthController extends Controller
|
class AuthController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -36,7 +35,7 @@ class AuthController extends Controller
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->poniverse = new Poniverse(Config::get('poniverse.client_id'), Config::get('poniverse.secret'));
|
$this->poniverse = new Poniverse(Config::get('poniverse.client_id'), Config::get('poniverse.secret'));
|
||||||
$this->poniverse->setRedirectUri(URL::to('/auth/oauth'));
|
$this->poniverse->setRedirectUri(action('AuthController@getOAuth'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLogin()
|
public function getLogin()
|
||||||
|
@ -62,7 +61,7 @@ class AuthController extends Controller
|
||||||
'authorization_code',
|
'authorization_code',
|
||||||
[
|
[
|
||||||
'code' => Input::query('code'),
|
'code' => Input::query('code'),
|
||||||
'redirect_uri' => URL::to('/auth/oauth')
|
'redirect_uri' => action('AuthController@getOAuth')
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($code['code'] != 200) {
|
if ($code['code'] != 200) {
|
||||||
|
|
|
@ -25,7 +25,6 @@ use Config;
|
||||||
use Illuminate\Support\Facades\App;
|
use Illuminate\Support\Facades\App;
|
||||||
use Illuminate\Support\Facades\Redirect;
|
use Illuminate\Support\Facades\Redirect;
|
||||||
use Response;
|
use Response;
|
||||||
use URL;
|
|
||||||
|
|
||||||
class ImagesController extends Controller
|
class ImagesController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -46,7 +45,7 @@ class ImagesController extends Controller
|
||||||
$filename = $image->getFile($coverType['id']);
|
$filename = $image->getFile($coverType['id']);
|
||||||
|
|
||||||
if (!is_file($filename)) {
|
if (!is_file($filename)) {
|
||||||
$redirect = URL::to('/images/icons/profile_' . Image::$ImageTypes[$coverType['id']]['name'] . '.png');
|
$redirect = url('/images/icons/profile_' . Image::$ImageTypes[$coverType['id']]['name'] . '.png');
|
||||||
|
|
||||||
return Redirect::to($redirect);
|
return Redirect::to($redirect);
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,8 +62,6 @@ Route::get('/mlpforums-advertising-program', function() { return View::make('pag
|
||||||
|
|
||||||
Route::get('i{id}/{type}.png', 'ImagesController@getImage')->where('id', '\d+');
|
Route::get('i{id}/{type}.png', 'ImagesController@getImage')->where('id', '\d+');
|
||||||
|
|
||||||
Route::get('u{id}/avatar_{type}.png', 'UsersController@getAvatar')->where('id', '\d+');
|
|
||||||
|
|
||||||
Route::get('playlist/{id}-{slug}', 'PlaylistsController@getPlaylist');
|
Route::get('playlist/{id}-{slug}', 'PlaylistsController@getPlaylist');
|
||||||
Route::get('p{id}', 'PlaylistsController@getShortlink')->where('id', '\d+');
|
Route::get('p{id}', 'PlaylistsController@getShortlink')->where('id', '\d+');
|
||||||
Route::get('p{id}/dl.{extension}', 'PlaylistsController@getDownload' );
|
Route::get('p{id}/dl.{extension}', 'PlaylistsController@getDownload' );
|
||||||
|
@ -101,6 +99,7 @@ Route::group(['prefix' => 'api/web'], function() {
|
||||||
|
|
||||||
Route::group(['middleware' => 'auth'], function() {
|
Route::group(['middleware' => 'auth'], function() {
|
||||||
Route::post('/tracks/upload', 'Api\Web\TracksController@postUpload');
|
Route::post('/tracks/upload', 'Api\Web\TracksController@postUpload');
|
||||||
|
Route::get('/tracks/{id}/upload-status', 'Api\Web\TracksController@getUploadStatus');
|
||||||
Route::post('/tracks/delete/{id}', 'Api\Web\TracksController@postDelete');
|
Route::post('/tracks/delete/{id}', 'Api\Web\TracksController@postDelete');
|
||||||
Route::post('/tracks/edit/{id}', 'Api\Web\TracksController@postEdit');
|
Route::post('/tracks/edit/{id}', 'Api\Web\TracksController@postEdit');
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,7 @@ namespace Poniverse\Ponyfm;
|
||||||
|
|
||||||
use External;
|
use External;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Support\Facades\Config;
|
use Config;
|
||||||
use Illuminate\Support\Facades\URL;
|
|
||||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||||
|
|
||||||
class Image extends Model
|
class Image extends Model
|
||||||
|
@ -101,7 +100,7 @@ class Image extends Model
|
||||||
{
|
{
|
||||||
$type = self::$ImageTypes[$type];
|
$type = self::$ImageTypes[$type];
|
||||||
|
|
||||||
return URL::to('i' . $this->id . '/' . $type['name'] . '.png');
|
return action('ImagesController@getImage', ['id' => $this->id, 'type' => $type['name']]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFile($type = self::NORMAL)
|
public function getFile($type = self::NORMAL)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pony.fm - A community for pony fan music.
|
* Pony.fm - A community for pony fan music.
|
||||||
|
* Copyright (C) 2015 Peter Deltchev
|
||||||
* Copyright (C) 2015 Kelvin Zhang
|
* Copyright (C) 2015 Kelvin Zhang
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -21,9 +22,11 @@
|
||||||
namespace Poniverse\Ponyfm\Jobs;
|
namespace Poniverse\Ponyfm\Jobs;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
use File;
|
||||||
use Illuminate\Support\Facades\Config;
|
use Illuminate\Support\Facades\Config;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use OAuth2\Exception;
|
use OAuth2\Exception;
|
||||||
|
use Poniverse\Ponyfm\Exceptions\InvalidEncodeOptionsException;
|
||||||
use Poniverse\Ponyfm\Jobs\Job;
|
use Poniverse\Ponyfm\Jobs\Job;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
@ -45,16 +48,29 @@ class EncodeTrackFile extends Job implements SelfHandling, ShouldQueue
|
||||||
* @var
|
* @var
|
||||||
*/
|
*/
|
||||||
private $isExpirable;
|
private $isExpirable;
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $isForUpload;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new job instance.
|
* Create a new job instance.
|
||||||
* @param TrackFile $trackFile
|
* @param TrackFile $trackFile
|
||||||
* @param $isExpirable
|
* @param bool $isExpirable
|
||||||
|
* @param bool $isForUpload indicates whether this encode job is for an upload
|
||||||
*/
|
*/
|
||||||
public function __construct(TrackFile $trackFile, $isExpirable)
|
public function __construct(TrackFile $trackFile, $isExpirable, $isForUpload = false)
|
||||||
{
|
{
|
||||||
|
if(
|
||||||
|
(!$isForUpload && $trackFile->is_master) ||
|
||||||
|
($isForUpload && $trackFile->is_master && !$trackFile->getFormat()['is_lossless'])
|
||||||
|
) {
|
||||||
|
throw new InvalidEncodeOptionsException("Master files cannot be encoded unless we're generating a lossless master file during the upload process.");
|
||||||
|
}
|
||||||
|
|
||||||
$this->trackFile = $trackFile;
|
$this->trackFile = $trackFile;
|
||||||
$this->isExpirable = $isExpirable;
|
$this->isExpirable = $isExpirable;
|
||||||
|
$this->isForUpload = $isForUpload;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -65,14 +81,19 @@ class EncodeTrackFile extends Job implements SelfHandling, ShouldQueue
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
// Start the job
|
// Start the job
|
||||||
$this->trackFile->is_in_progress = true;
|
$this->trackFile->status = TrackFile::STATUS_PROCESSING;
|
||||||
$this->trackFile->update();
|
$this->trackFile->update();
|
||||||
|
|
||||||
// Use the track's master file as the source
|
// Use the track's master file as the source
|
||||||
$source = TrackFile::where('track_id', $this->trackFile->track_id)
|
if ($this->isForUpload) {
|
||||||
->where('is_master', true)
|
$source = $this->trackFile->track->getTemporarySourceFile();
|
||||||
->first()
|
|
||||||
->getFile();
|
} else {
|
||||||
|
$source = TrackFile::where('track_id', $this->trackFile->track_id)
|
||||||
|
->where('is_master', true)
|
||||||
|
->first()
|
||||||
|
->getFile();
|
||||||
|
}
|
||||||
|
|
||||||
// Assign the target
|
// Assign the target
|
||||||
$this->trackFile->track->ensureDirectoryExists();
|
$this->trackFile->track->ensureDirectoryExists();
|
||||||
|
@ -111,8 +132,18 @@ class EncodeTrackFile extends Job implements SelfHandling, ShouldQueue
|
||||||
$this->trackFile->updateFilesize();
|
$this->trackFile->updateFilesize();
|
||||||
|
|
||||||
// Complete the job
|
// Complete the job
|
||||||
$this->trackFile->is_in_progress = false;
|
$this->trackFile->status = TrackFile::STATUS_NOT_BEING_PROCESSED;
|
||||||
$this->trackFile->update();
|
$this->trackFile->update();
|
||||||
|
|
||||||
|
if ($this->isForUpload) {
|
||||||
|
if (!$this->trackFile->is_master && $this->trackFile->is_cacheable) {
|
||||||
|
File::delete($this->trackFile->getFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->trackFile->track->status === Track::STATUS_COMPLETE) {
|
||||||
|
File::delete($this->trackFile->track->getTemporarySourceFile());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -122,7 +153,7 @@ class EncodeTrackFile extends Job implements SelfHandling, ShouldQueue
|
||||||
*/
|
*/
|
||||||
public function failed()
|
public function failed()
|
||||||
{
|
{
|
||||||
$this->trackFile->is_in_progress = false;
|
$this->trackFile->status = TrackFile::STATUS_PROCESSING_ERROR;
|
||||||
$this->trackFile->expires_at = null;
|
$this->trackFile->expires_at = null;
|
||||||
$this->trackFile->update();
|
$this->trackFile->update();
|
||||||
}
|
}
|
||||||
|
|
0
app/Library/getid3/.gitattributes
vendored
Executable file → Normal file
0
app/Library/getid3/.gitattributes
vendored
Executable file → Normal file
7
app/Library/getid3/.gitignore
vendored
Executable file → Normal file
7
app/Library/getid3/.gitignore
vendored
Executable file → Normal file
|
@ -1,4 +1,4 @@
|
||||||
helperapps/sha1sum.exe
|
helperapps/*.exe
|
||||||
helperapps/*.dll
|
helperapps/*.dll
|
||||||
|
|
||||||
|
|
||||||
|
@ -110,7 +110,9 @@ ClientBin
|
||||||
stylecop.*
|
stylecop.*
|
||||||
~$*
|
~$*
|
||||||
*.dbmdl
|
*.dbmdl
|
||||||
Generated_Code #added for RIA/Silverlight projects
|
|
||||||
|
#added for RIA/Silverlight projects
|
||||||
|
Generated_Code
|
||||||
|
|
||||||
# Backup & report files from converting an old project file to a newer
|
# Backup & report files from converting an old project file to a newer
|
||||||
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
||||||
|
@ -165,3 +167,4 @@ pip-log.txt
|
||||||
|
|
||||||
# Mac crap
|
# Mac crap
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
demos/php_error.log
|
||||||
|
|
2
app/Library/getid3/README.md
Executable file → Normal file
2
app/Library/getid3/README.md
Executable file → Normal file
|
@ -186,7 +186,7 @@ if ($fp_remote = fopen($remotefilename, 'rb')) {
|
||||||
fclose($fp_local);
|
fclose($fp_local);
|
||||||
// Initialize getID3 engine
|
// Initialize getID3 engine
|
||||||
$getID3 = new getID3;
|
$getID3 = new getID3;
|
||||||
$ThisFileInfo = $getID3->analyze($filename);
|
$ThisFileInfo = $getID3->analyze($localtempfilename);
|
||||||
// Delete temporary file
|
// Delete temporary file
|
||||||
unlink($localtempfilename);
|
unlink($localtempfilename);
|
||||||
}
|
}
|
||||||
|
|
11
app/Library/getid3/changelog.txt
Executable file → Normal file
11
app/Library/getid3/changelog.txt
Executable file → Normal file
|
@ -18,6 +18,17 @@
|
||||||
Version History
|
Version History
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
1.9.10: [2015-09-14] James Heinrich
|
||||||
|
* bugfix (G:49): Declaration of getID3_cached_sqlite3
|
||||||
|
* bugfix (#1892): extension.cache.mysql
|
||||||
|
* bugfix (#1891): duplicate default clause [Quicktime]
|
||||||
|
* bugfix (G:41): incorrect MP3 playtime
|
||||||
|
* bugfix: iconv problems on musl with //TRANSLIT
|
||||||
|
* Add arguments to analyze() for original filesize (and filename)
|
||||||
|
* ID3v2 simplify handling of multiple genres
|
||||||
|
* Corrected merging of multiple genres for ID3v2
|
||||||
|
* getid3_lib::GetDataImageSize return false on error
|
||||||
|
|
||||||
1.9.9: [2014-12-18] James Heinrich
|
1.9.9: [2014-12-18] James Heinrich
|
||||||
» Added basic support for OggOpus
|
» Added basic support for OggOpus
|
||||||
» Add ID3v2 CHAP + CTOC support
|
» Add ID3v2 CHAP + CTOC support
|
||||||
|
|
0
app/Library/getid3/composer.json
Executable file → Normal file
0
app/Library/getid3/composer.json
Executable file → Normal file
0
app/Library/getid3/demos/demo.audioinfo.class.php
Executable file → Normal file
0
app/Library/getid3/demos/demo.audioinfo.class.php
Executable file → Normal file
0
app/Library/getid3/demos/demo.basic.php
Executable file → Normal file
0
app/Library/getid3/demos/demo.basic.php
Executable file → Normal file
10
app/Library/getid3/demos/demo.browse.php
Executable file → Normal file
10
app/Library/getid3/demos/demo.browse.php
Executable file → Normal file
|
@ -480,8 +480,11 @@ function table_var_dump($variable, $wrap_in_td=false, $encoding='ISO-8859-1') {
|
||||||
//if (($key == 'data') && isset($variable['image_mime']) && isset($variable['dataoffset'])) {
|
//if (($key == 'data') && isset($variable['image_mime']) && isset($variable['dataoffset'])) {
|
||||||
if (($key == 'data') && isset($variable['image_mime'])) {
|
if (($key == 'data') && isset($variable['image_mime'])) {
|
||||||
$imageinfo = array();
|
$imageinfo = array();
|
||||||
$imagechunkcheck = getid3_lib::GetDataImageSize($value, $imageinfo);
|
if ($imagechunkcheck = getid3_lib::GetDataImageSize($value, $imageinfo)) {
|
||||||
$returnstring .= '</td>'."\n".'<td><img src="data:'.$variable['image_mime'].';base64,'.base64_encode($value).'" width="'.$imagechunkcheck[0].'" height="'.$imagechunkcheck[1].'"></td></tr>'."\n";
|
$returnstring .= '</td>'."\n".'<td><img src="data:'.$variable['image_mime'].';base64,'.base64_encode($value).'" width="'.$imagechunkcheck[0].'" height="'.$imagechunkcheck[1].'"></td></tr>'."\n";
|
||||||
|
} else {
|
||||||
|
$returnstring .= '</td>'."\n".'<td><i>invalid image data</i></td></tr>'."\n";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$returnstring .= '</td>'."\n".table_var_dump($value, true, $encoding).'</tr>'."\n";
|
$returnstring .= '</td>'."\n".table_var_dump($value, true, $encoding).'</tr>'."\n";
|
||||||
}
|
}
|
||||||
|
@ -515,8 +518,7 @@ function table_var_dump($variable, $wrap_in_td=false, $encoding='ISO-8859-1') {
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$imageinfo = array();
|
$imageinfo = array();
|
||||||
$imagechunkcheck = getid3_lib::GetDataImageSize($variable, $imageinfo);
|
if (($imagechunkcheck = getid3_lib::GetDataImageSize($variable, $imageinfo)) && ($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) {
|
||||||
if (($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) {
|
|
||||||
$returnstring .= ($wrap_in_td ? '<td>' : '');
|
$returnstring .= ($wrap_in_td ? '<td>' : '');
|
||||||
$returnstring .= '<table class="dump" cellspacing="0" cellpadding="2">';
|
$returnstring .= '<table class="dump" cellspacing="0" cellpadding="2">';
|
||||||
$returnstring .= '<tr><td><b>type</b></td><td>'.getid3_lib::ImageTypesLookup($imagechunkcheck[2]).'</td></tr>'."\n";
|
$returnstring .= '<tr><td><b>type</b></td><td>'.getid3_lib::ImageTypesLookup($imagechunkcheck[2]).'</td></tr>'."\n";
|
||||||
|
|
0
app/Library/getid3/demos/demo.cache.dbm.php
Executable file → Normal file
0
app/Library/getid3/demos/demo.cache.dbm.php
Executable file → Normal file
1
app/Library/getid3/demos/demo.cache.mysql.php
Executable file → Normal file
1
app/Library/getid3/demos/demo.cache.mysql.php
Executable file → Normal file
|
@ -17,6 +17,7 @@ die('Due to a security issue, this demo has been disabled. It can be enabled by
|
||||||
|
|
||||||
|
|
||||||
require_once('../getid3/getid3.php');
|
require_once('../getid3/getid3.php');
|
||||||
|
require_once('../getid3/getid3.lib.php');
|
||||||
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'extension.cache.mysql.php', __FILE__, true);
|
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'extension.cache.mysql.php', __FILE__, true);
|
||||||
|
|
||||||
$getID3 = new getID3_cached_mysql('localhost', 'database', 'username', 'password');
|
$getID3 = new getID3_cached_mysql('localhost', 'database', 'username', 'password');
|
||||||
|
|
72
app/Library/getid3/demos/demo.joinmp3.php
Executable file → Normal file
72
app/Library/getid3/demos/demo.joinmp3.php
Executable file → Normal file
|
@ -9,37 +9,47 @@
|
||||||
// /demo/demo.joinmp3.php - part of getID3() //
|
// /demo/demo.joinmp3.php - part of getID3() //
|
||||||
// Sample script for splicing two or more MP3s together into //
|
// Sample script for splicing two or more MP3s together into //
|
||||||
// one file. Does not attempt to fix VBR header frames. //
|
// one file. Does not attempt to fix VBR header frames. //
|
||||||
|
// Can also be used to extract portion from single file. //
|
||||||
// See readme.txt for more details //
|
// See readme.txt for more details //
|
||||||
// ///
|
// ///
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
// sample usage:
|
// sample usage:
|
||||||
// $FilenameOut = 'combined.mp3';
|
// $FilenameOut = 'combined.mp3';
|
||||||
// $FilenamesIn[] = 'file1.mp3';
|
// $FilenamesIn[] = 'first.mp3'; // filename with no start/length parameters
|
||||||
// $FilenamesIn[] = 'file2.mp3';
|
// $FilenamesIn[] = array('second.mp3', 0, 0); // filename with zero for start/length is the same as not specified (start = beginning, length = full duration)
|
||||||
// $FilenamesIn[] = 'file3.mp3';
|
// $FilenamesIn[] = array('third.mp3', 0, 10); // extract first 10 seconds of audio
|
||||||
|
// $FilenamesIn[] = array('fourth.mp3', -10, 0); // extract last 10 seconds of audio
|
||||||
|
// $FilenamesIn[] = array('fifth.mp3', 10, 0); // extract everything except first 10 seconds of audio
|
||||||
|
// $FilenamesIn[] = array('sixth.mp3', 0, -10); // extract everything except last 10 seconds of audio
|
||||||
|
// if (CombineMultipleMP3sTo($FilenameOut, $FilenamesIn)) {
|
||||||
|
// echo 'Successfully copied '.implode(' + ', $FilenamesIn).' to '.$FilenameOut;
|
||||||
|
// } else {
|
||||||
|
// echo 'Failed to copy '.implode(' + ', $FilenamesIn).' to '.$FilenameOut;
|
||||||
|
// }
|
||||||
//
|
//
|
||||||
// if (CombineMultipleMP3sTo($FilenameOut, $FilenamesIn)) {
|
// Could also be called like this to extract portion from single file:
|
||||||
// echo 'Successfully copied '.implode(' + ', $FilenamesIn).' to '.$FilenameOut;
|
// CombineMultipleMP3sTo('sample.mp3', array(array('input.mp3', 0, 30))); // extract first 30 seconds of audio
|
||||||
// } else {
|
|
||||||
// echo 'Failed to copy '.implode(' + ', $FilenamesIn).' to '.$FilenameOut;
|
|
||||||
// }
|
|
||||||
|
|
||||||
function CombineMultipleMP3sTo($FilenameOut, $FilenamesIn) {
|
function CombineMultipleMP3sTo($FilenameOut, $FilenamesIn) {
|
||||||
|
|
||||||
foreach ($FilenamesIn as $nextinputfilename) {
|
foreach ($FilenamesIn as $nextinputfilename) {
|
||||||
|
if (is_array($nextinputfilename)) {
|
||||||
|
$nextinputfilename = $nextinputfilename[0];
|
||||||
|
}
|
||||||
if (!is_readable($nextinputfilename)) {
|
if (!is_readable($nextinputfilename)) {
|
||||||
echo 'Cannot read "'.$nextinputfilename.'"<BR>';
|
echo 'Cannot read "'.$nextinputfilename.'"<BR>';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!is_writeable($FilenameOut)) {
|
if ((file_exists($FilenameOut) && !is_writeable($FilenameOut)) || (!file_exists($FilenameOut) && !is_writeable(dirname($FilenameOut)))) {
|
||||||
echo 'Cannot write "'.$FilenameOut.'"<BR>';
|
echo 'Cannot write "'.$FilenameOut.'"<BR>';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
require_once('../getid3/getid3.php');
|
require_once(dirname(__FILE__).'/../getid3/getid3.php');
|
||||||
ob_start();
|
ob_start();
|
||||||
if ($fp_output = fopen($FilenameOut, 'wb')) {
|
if ($fp_output = fopen($FilenameOut, 'wb')) {
|
||||||
|
|
||||||
|
@ -47,7 +57,11 @@ function CombineMultipleMP3sTo($FilenameOut, $FilenamesIn) {
|
||||||
// Initialize getID3 engine
|
// Initialize getID3 engine
|
||||||
$getID3 = new getID3;
|
$getID3 = new getID3;
|
||||||
foreach ($FilenamesIn as $nextinputfilename) {
|
foreach ($FilenamesIn as $nextinputfilename) {
|
||||||
|
$startoffset = 0;
|
||||||
|
$length_seconds = 0;
|
||||||
|
if (is_array($nextinputfilename)) {
|
||||||
|
@list($nextinputfilename, $startoffset, $length_seconds) = $nextinputfilename;
|
||||||
|
}
|
||||||
$CurrentFileInfo = $getID3->analyze($nextinputfilename);
|
$CurrentFileInfo = $getID3->analyze($nextinputfilename);
|
||||||
if ($CurrentFileInfo['fileformat'] == 'mp3') {
|
if ($CurrentFileInfo['fileformat'] == 'mp3') {
|
||||||
|
|
||||||
|
@ -58,17 +72,35 @@ function CombineMultipleMP3sTo($FilenameOut, $FilenamesIn) {
|
||||||
$CurrentOutputPosition = ftell($fp_output);
|
$CurrentOutputPosition = ftell($fp_output);
|
||||||
|
|
||||||
// copy audio data from first file
|
// copy audio data from first file
|
||||||
fseek($fp_source, $CurrentFileInfo['avdataoffset'], SEEK_SET);
|
$start_offset_bytes = $CurrentFileInfo['avdataoffset'];
|
||||||
while (!feof($fp_source) && (ftell($fp_source) < $CurrentFileInfo['avdataend'])) {
|
if ($startoffset > 0) { // start X seconds from start of audio
|
||||||
fwrite($fp_output, fread($fp_source, 32768));
|
$start_offset_bytes = $CurrentFileInfo['avdataoffset'] + round($CurrentFileInfo['bitrate'] / 8 * $startoffset);
|
||||||
|
} elseif ($startoffset < 0) { // start X seconds from end of audio
|
||||||
|
$start_offset_bytes = $CurrentFileInfo['avdataend'] + round($CurrentFileInfo['bitrate'] / 8 * $startoffset);
|
||||||
|
}
|
||||||
|
$start_offset_bytes = max($CurrentFileInfo['avdataoffset'], min($CurrentFileInfo['avdataend'], $start_offset_bytes));
|
||||||
|
|
||||||
|
$end_offset_bytes = $CurrentFileInfo['avdataend'];
|
||||||
|
if ($length_seconds > 0) { // seconds from start of audio
|
||||||
|
$end_offset_bytes = $start_offset_bytes + round($CurrentFileInfo['bitrate'] / 8 * $length_seconds);
|
||||||
|
} elseif ($length_seconds < 0) { // seconds from start of audio
|
||||||
|
$end_offset_bytes = $CurrentFileInfo['avdataend'] + round($CurrentFileInfo['bitrate'] / 8 * $startoffset);
|
||||||
|
}
|
||||||
|
$end_offset_bytes = max($CurrentFileInfo['avdataoffset'], min($CurrentFileInfo['avdataend'], $end_offset_bytes));
|
||||||
|
|
||||||
|
if ($end_offset_bytes <= $start_offset_bytes) {
|
||||||
|
echo 'failed to copy '.$nextinputfilename.' from '.$startoffset.'-seconds start for '.$length_seconds.'-seconds length (not enough data)';
|
||||||
|
fclose($fp_source);
|
||||||
|
fclose($fp_output);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek($fp_source, $start_offset_bytes, SEEK_SET);
|
||||||
|
while (!feof($fp_source) && (ftell($fp_source) < $end_offset_bytes)) {
|
||||||
|
fwrite($fp_output, fread($fp_source, min(32768, $end_offset_bytes - ftell($fp_source))));
|
||||||
}
|
}
|
||||||
fclose($fp_source);
|
fclose($fp_source);
|
||||||
|
|
||||||
// trim post-audio data (if any) copied from first file that we don't need or want
|
|
||||||
$EndOfFileOffset = $CurrentOutputPosition + ($CurrentFileInfo['avdataend'] - $CurrentFileInfo['avdataoffset']);
|
|
||||||
fseek($fp_output, $EndOfFileOffset, SEEK_SET);
|
|
||||||
ftruncate($fp_output, $EndOfFileOffset);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
$errormessage = ob_get_contents();
|
$errormessage = ob_get_contents();
|
||||||
|
|
0
app/Library/getid3/demos/demo.mimeonly.php
Executable file → Normal file
0
app/Library/getid3/demos/demo.mimeonly.php
Executable file → Normal file
29
app/Library/getid3/demos/demo.mp3header.php
Executable file → Normal file
29
app/Library/getid3/demos/demo.mp3header.php
Executable file → Normal file
|
@ -29,10 +29,10 @@ if (!function_exists('table_var_dump')) {
|
||||||
$returnstring = '';
|
$returnstring = '';
|
||||||
switch (gettype($variable)) {
|
switch (gettype($variable)) {
|
||||||
case 'array':
|
case 'array':
|
||||||
$returnstring .= '<TABLE BORDER="1" CELLSPACING="0" CELLPADDING="2">';
|
$returnstring .= '<table border="1" cellspacing="0" cellpadding="2">';
|
||||||
foreach ($variable as $key => $value) {
|
foreach ($variable as $key => $value) {
|
||||||
$returnstring .= '<TR><TD VALIGN="TOP"><B>'.str_replace(chr(0), ' ', $key).'</B></TD>';
|
$returnstring .= '<tr><td valign="top"><b>'.str_replace(chr(0), ' ', $key).'</b></td>';
|
||||||
$returnstring .= '<TD VALIGN="TOP">'.gettype($value);
|
$returnstring .= '<td valign="top">'.gettype($value);
|
||||||
if (is_array($value)) {
|
if (is_array($value)) {
|
||||||
$returnstring .= ' ('.count($value).')';
|
$returnstring .= ' ('.count($value).')';
|
||||||
} elseif (is_string($value)) {
|
} elseif (is_string($value)) {
|
||||||
|
@ -41,18 +41,21 @@ if (!function_exists('table_var_dump')) {
|
||||||
if (($key == 'data') && isset($variable['image_mime']) && isset($variable['dataoffset'])) {
|
if (($key == 'data') && isset($variable['image_mime']) && isset($variable['dataoffset'])) {
|
||||||
require_once(GETID3_INCLUDEPATH.'getid3.getimagesize.php');
|
require_once(GETID3_INCLUDEPATH.'getid3.getimagesize.php');
|
||||||
$imageinfo = array();
|
$imageinfo = array();
|
||||||
$imagechunkcheck = GetDataImageSize($value, $imageinfo);
|
if ($imagechunkcheck = GetDataImageSize($value, $imageinfo)) {
|
||||||
$DumpedImageSRC = (!empty($_REQUEST['filename']) ? $_REQUEST['filename'] : '.getid3').'.'.$variable['dataoffset'].'.'.ImageTypesLookup($imagechunkcheck[2]);
|
$DumpedImageSRC = (!empty($_REQUEST['filename']) ? $_REQUEST['filename'] : '.getid3').'.'.$variable['dataoffset'].'.'.ImageTypesLookup($imagechunkcheck[2]);
|
||||||
if ($tempimagefile = fopen($DumpedImageSRC, 'wb')) {
|
if ($tempimagefile = fopen($DumpedImageSRC, 'wb')) {
|
||||||
fwrite($tempimagefile, $value);
|
fwrite($tempimagefile, $value);
|
||||||
fclose($tempimagefile);
|
fclose($tempimagefile);
|
||||||
|
}
|
||||||
|
$returnstring .= '</td><td><img src="'.$DumpedImageSRC.'" width="'.$imagechunkcheck[0].'" height="'.$imagechunkcheck[1].'"></td></tr>';
|
||||||
|
} else {
|
||||||
|
$returnstring .= '</td><td><i>invalid image data</i></td></tr>';
|
||||||
}
|
}
|
||||||
$returnstring .= '</TD><TD><IMG SRC="'.$DumpedImageSRC.'" WIDTH="'.$imagechunkcheck[0].'" HEIGHT="'.$imagechunkcheck[1].'"></TD></TR>';
|
|
||||||
} else {
|
} else {
|
||||||
$returnstring .= '</TD><TD>'.table_var_dump($value).'</TD></TR>';
|
$returnstring .= '</td><td>'.table_var_dump($value).'</td></tr>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$returnstring .= '</TABLE>';
|
$returnstring .= '</table>';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'boolean':
|
case 'boolean':
|
||||||
|
@ -86,9 +89,7 @@ if (!function_exists('table_var_dump')) {
|
||||||
default:
|
default:
|
||||||
require_once(GETID3_INCLUDEPATH.'getid3.getimagesize.php');
|
require_once(GETID3_INCLUDEPATH.'getid3.getimagesize.php');
|
||||||
$imageinfo = array();
|
$imageinfo = array();
|
||||||
$imagechunkcheck = GetDataImageSize(substr($variable, 0, 32768), $imageinfo);
|
if (($imagechunkcheck = GetDataImageSize(substr($variable, 0, 32768), $imageinfo)) && ($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) {
|
||||||
|
|
||||||
if (($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) {
|
|
||||||
$returnstring .= '<table border="1" cellspacing="0" cellpadding="2">';
|
$returnstring .= '<table border="1" cellspacing="0" cellpadding="2">';
|
||||||
$returnstring .= '<tr><td><b>type</b></td><td>'.ImageTypesLookup($imagechunkcheck[2]).'</td></tr>';
|
$returnstring .= '<tr><td><b>type</b></td><td>'.ImageTypesLookup($imagechunkcheck[2]).'</td></tr>';
|
||||||
$returnstring .= '<tr><td><b>width</b></td><td>'.number_format($imagechunkcheck[0]).' px</td></tr>';
|
$returnstring .= '<tr><td><b>width</b></td><td>'.number_format($imagechunkcheck[0]).' px</td></tr>';
|
||||||
|
|
0
app/Library/getid3/demos/demo.mysql.php
Executable file → Normal file
0
app/Library/getid3/demos/demo.mysql.php
Executable file → Normal file
0
app/Library/getid3/demos/demo.simple.php
Executable file → Normal file
0
app/Library/getid3/demos/demo.simple.php
Executable file → Normal file
0
app/Library/getid3/demos/demo.simple.write.php
Executable file → Normal file
0
app/Library/getid3/demos/demo.simple.write.php
Executable file → Normal file
0
app/Library/getid3/demos/demo.write.php
Executable file → Normal file
0
app/Library/getid3/demos/demo.write.php
Executable file → Normal file
0
app/Library/getid3/demos/demo.zip.php
Executable file → Normal file
0
app/Library/getid3/demos/demo.zip.php
Executable file → Normal file
0
app/Library/getid3/demos/getid3.css
vendored
Executable file → Normal file
0
app/Library/getid3/demos/getid3.css
vendored
Executable file → Normal file
0
app/Library/getid3/demos/getid3.demo.dirscan.php
Executable file → Normal file
0
app/Library/getid3/demos/getid3.demo.dirscan.php
Executable file → Normal file
0
app/Library/getid3/demos/index.php
Executable file → Normal file
0
app/Library/getid3/demos/index.php
Executable file → Normal file
0
app/Library/getid3/dependencies.txt
Executable file → Normal file
0
app/Library/getid3/dependencies.txt
Executable file → Normal file
2
app/Library/getid3/getid3/extension.cache.dbm.php
Executable file → Normal file
2
app/Library/getid3/getid3/extension.cache.dbm.php
Executable file → Normal file
|
@ -74,7 +74,7 @@ class getID3_cached_dbm extends getID3
|
||||||
{
|
{
|
||||||
|
|
||||||
// public: constructor - see top of this file for cache type and cache_options
|
// public: constructor - see top of this file for cache type and cache_options
|
||||||
public function getID3_cached_dbm($cache_type, $dbm_filename, $lock_filename) {
|
public function __construct($cache_type, $dbm_filename, $lock_filename) {
|
||||||
|
|
||||||
// Check for dba extension
|
// Check for dba extension
|
||||||
if (!extension_loaded('dba')) {
|
if (!extension_loaded('dba')) {
|
||||||
|
|
10
app/Library/getid3/getid3/extension.cache.mysql.php
Executable file → Normal file
10
app/Library/getid3/getid3/extension.cache.mysql.php
Executable file → Normal file
|
@ -80,7 +80,7 @@ class getID3_cached_mysql extends getID3
|
||||||
|
|
||||||
|
|
||||||
// public: constructor - see top of this file for cache type and cache_options
|
// public: constructor - see top of this file for cache type and cache_options
|
||||||
public function getID3_cached_mysql($host, $database, $username, $password, $table='getid3_cache') {
|
public function __construct($host, $database, $username, $password, $table='getid3_cache') {
|
||||||
|
|
||||||
// Check for mysql support
|
// Check for mysql support
|
||||||
if (!function_exists('mysql_pconnect')) {
|
if (!function_exists('mysql_pconnect')) {
|
||||||
|
@ -134,7 +134,7 @@ class getID3_cached_mysql extends getID3
|
||||||
|
|
||||||
|
|
||||||
// public: analyze file
|
// public: analyze file
|
||||||
public function analyze($filename) {
|
public function analyze($filename, $filesize=null, $original_filename='') {
|
||||||
|
|
||||||
if (file_exists($filename)) {
|
if (file_exists($filename)) {
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ class getID3_cached_mysql extends getID3
|
||||||
}
|
}
|
||||||
|
|
||||||
// Miss
|
// Miss
|
||||||
$analysis = parent::analyze($filename);
|
$analysis = parent::analyze($filename, $filesize, $original_filename);
|
||||||
|
|
||||||
// Save result
|
// Save result
|
||||||
if (file_exists($filename)) {
|
if (file_exists($filename)) {
|
||||||
|
@ -178,11 +178,11 @@ class getID3_cached_mysql extends getID3
|
||||||
private function create_table($drop=false) {
|
private function create_table($drop=false) {
|
||||||
|
|
||||||
$SQLquery = 'CREATE TABLE IF NOT EXISTS `'.mysql_real_escape_string($this->table).'` (';
|
$SQLquery = 'CREATE TABLE IF NOT EXISTS `'.mysql_real_escape_string($this->table).'` (';
|
||||||
$SQLquery .= '`filename` VARCHAR(255) NOT NULL DEFAULT \'\'';
|
$SQLquery .= '`filename` VARCHAR(500) NOT NULL DEFAULT \'\'';
|
||||||
$SQLquery .= ', `filesize` INT(11) NOT NULL DEFAULT \'0\'';
|
$SQLquery .= ', `filesize` INT(11) NOT NULL DEFAULT \'0\'';
|
||||||
$SQLquery .= ', `filetime` INT(11) NOT NULL DEFAULT \'0\'';
|
$SQLquery .= ', `filetime` INT(11) NOT NULL DEFAULT \'0\'';
|
||||||
$SQLquery .= ', `analyzetime` INT(11) NOT NULL DEFAULT \'0\'';
|
$SQLquery .= ', `analyzetime` INT(11) NOT NULL DEFAULT \'0\'';
|
||||||
$SQLquery .= ', `value` TEXT NOT NULL';
|
$SQLquery .= ', `value` LONGTEXT NOT NULL';
|
||||||
$SQLquery .= ', PRIMARY KEY (`filename`, `filesize`, `filetime`)) ENGINE=MyISAM';
|
$SQLquery .= ', PRIMARY KEY (`filename`, `filesize`, `filetime`)) ENGINE=MyISAM';
|
||||||
$this->cursor = mysql_query($SQLquery, $this->connection);
|
$this->cursor = mysql_query($SQLquery, $this->connection);
|
||||||
echo mysql_error($this->connection);
|
echo mysql_error($this->connection);
|
||||||
|
|
55
app/Library/getid3/getid3/extension.cache.sqlite3.php
Executable file → Normal file
55
app/Library/getid3/getid3/extension.cache.sqlite3.php
Executable file → Normal file
|
@ -49,20 +49,20 @@
|
||||||
*
|
*
|
||||||
* sqlite3 table='getid3_cache', hide=false (PHP5)
|
* sqlite3 table='getid3_cache', hide=false (PHP5)
|
||||||
*
|
*
|
||||||
|
*
|
||||||
*** database file will be stored in the same directory as this script,
|
* *** database file will be stored in the same directory as this script,
|
||||||
*** webserver must have write access to that directory!
|
* *** webserver must have write access to that directory!
|
||||||
*** set $hide to TRUE to prefix db file with .ht to pervent access from web client
|
* *** set $hide to TRUE to prefix db file with .ht to pervent access from web client
|
||||||
*** this is a default setting in the Apache configuration:
|
* *** this is a default setting in the Apache configuration:
|
||||||
|
*
|
||||||
# The following lines prevent .htaccess and .htpasswd files from being viewed by Web clients.
|
* The following lines prevent .htaccess and .htpasswd files from being viewed by Web clients.
|
||||||
|
*
|
||||||
<Files ~ "^\.ht">
|
* <Files ~ "^\.ht">
|
||||||
Order allow,deny
|
* Order allow,deny
|
||||||
Deny from all
|
* Deny from all
|
||||||
Satisfy all
|
* Satisfy all
|
||||||
</Files>
|
* </Files>
|
||||||
|
*
|
||||||
********************************************************************************
|
********************************************************************************
|
||||||
*
|
*
|
||||||
* -------------------------------------------------------------------
|
* -------------------------------------------------------------------
|
||||||
|
@ -159,13 +159,13 @@ class getID3_cached_sqlite3 extends getID3 {
|
||||||
* @param type $filename
|
* @param type $filename
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function analyze($filename) {
|
public function analyze($filename, $filesize=null, $original_filename='') {
|
||||||
if (!file_exists($filename)) {
|
if (!file_exists($filename)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// items to track for caching
|
// items to track for caching
|
||||||
$filetime = filemtime($filename);
|
$filetime = filemtime($filename);
|
||||||
$filesize = filesize($filename);
|
$filesize_real = filesize($filename);
|
||||||
// this will be saved for a quick directory lookup of analized files
|
// this will be saved for a quick directory lookup of analized files
|
||||||
// ... why do 50 seperate sql quries when you can do 1 for the same result
|
// ... why do 50 seperate sql quries when you can do 1 for the same result
|
||||||
$dirname = dirname($filename);
|
$dirname = dirname($filename);
|
||||||
|
@ -173,25 +173,25 @@ class getID3_cached_sqlite3 extends getID3 {
|
||||||
$db = $this->db;
|
$db = $this->db;
|
||||||
$sql = $this->get_id3_data;
|
$sql = $this->get_id3_data;
|
||||||
$stmt = $db->prepare($sql);
|
$stmt = $db->prepare($sql);
|
||||||
$stmt->bindValue(':filename', $filename, SQLITE3_TEXT);
|
$stmt->bindValue(':filename', $filename, SQLITE3_TEXT);
|
||||||
$stmt->bindValue(':filesize', $filesize, SQLITE3_INTEGER);
|
$stmt->bindValue(':filesize', $filesize_real, SQLITE3_INTEGER);
|
||||||
$stmt->bindValue(':filetime', $filetime, SQLITE3_INTEGER);
|
$stmt->bindValue(':filetime', $filetime, SQLITE3_INTEGER);
|
||||||
$res = $stmt->execute();
|
$res = $stmt->execute();
|
||||||
list($result) = $res->fetchArray();
|
list($result) = $res->fetchArray();
|
||||||
if (count($result) > 0 ) {
|
if (count($result) > 0 ) {
|
||||||
return unserialize(base64_decode($result));
|
return unserialize(base64_decode($result));
|
||||||
}
|
}
|
||||||
// if it hasn't been analyzed before, then do it now
|
// if it hasn't been analyzed before, then do it now
|
||||||
$analysis = parent::analyze($filename);
|
$analysis = parent::analyze($filename, $filesize, $original_filename);
|
||||||
// Save result
|
// Save result
|
||||||
$sql = $this->cache_file;
|
$sql = $this->cache_file;
|
||||||
$stmt = $db->prepare($sql);
|
$stmt = $db->prepare($sql);
|
||||||
$stmt->bindValue(':filename', $filename, SQLITE3_TEXT);
|
$stmt->bindValue(':filename', $filename, SQLITE3_TEXT);
|
||||||
$stmt->bindValue(':dirname', $dirname, SQLITE3_TEXT);
|
$stmt->bindValue(':dirname', $dirname, SQLITE3_TEXT);
|
||||||
$stmt->bindValue(':filesize', $filesize, SQLITE3_INTEGER);
|
$stmt->bindValue(':filesize', $filesize_real, SQLITE3_INTEGER);
|
||||||
$stmt->bindValue(':filetime', $filetime, SQLITE3_INTEGER);
|
$stmt->bindValue(':filetime', $filetime, SQLITE3_INTEGER);
|
||||||
$stmt->bindValue(':atime', time(), SQLITE3_INTEGER);
|
$stmt->bindValue(':atime', time(), SQLITE3_INTEGER);
|
||||||
$stmt->bindValue(':val', base64_encode(serialize($analysis)), SQLITE3_TEXT);
|
$stmt->bindValue(':val', base64_encode(serialize($analysis)), SQLITE3_TEXT);
|
||||||
$res = $stmt->execute();
|
$res = $stmt->execute();
|
||||||
return $analysis;
|
return $analysis;
|
||||||
}
|
}
|
||||||
|
@ -253,7 +253,8 @@ class getID3_cached_sqlite3 extends getID3 {
|
||||||
return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, :filesize, :filetime, :atime, :val)";
|
return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, :filesize, :filetime, :atime, :val)";
|
||||||
break;
|
break;
|
||||||
case 'make_table':
|
case 'make_table':
|
||||||
return "CREATE TABLE IF NOT EXISTS $this->table (filename VARCHAR(255) NOT NULL DEFAULT '', dirname VARCHAR(255) NOT NULL DEFAULT '', filesize INT(11) NOT NULL DEFAULT '0', filetime INT(11) NOT NULL DEFAULT '0', analyzetime INT(11) NOT NULL DEFAULT '0', val text not null, PRIMARY KEY (filename, filesize, filetime))";
|
//return "CREATE TABLE IF NOT EXISTS $this->table (filename VARCHAR(255) NOT NULL DEFAULT '', dirname VARCHAR(255) NOT NULL DEFAULT '', filesize INT(11) NOT NULL DEFAULT '0', filetime INT(11) NOT NULL DEFAULT '0', analyzetime INT(11) NOT NULL DEFAULT '0', val text not null, PRIMARY KEY (filename, filesize, filetime))";
|
||||||
|
return "CREATE TABLE IF NOT EXISTS $this->table (filename VARCHAR(255) DEFAULT '', dirname VARCHAR(255) DEFAULT '', filesize INT(11) DEFAULT '0', filetime INT(11) DEFAULT '0', analyzetime INT(11) DEFAULT '0', val text, PRIMARY KEY (filename, filesize, filetime))";
|
||||||
break;
|
break;
|
||||||
case 'get_cached_dir':
|
case 'get_cached_dir':
|
||||||
return "SELECT val FROM $this->table WHERE dirname = :dirname";
|
return "SELECT val FROM $this->table WHERE dirname = :dirname";
|
||||||
|
|
35
app/Library/getid3/getid3/getid3.lib.php
Executable file → Normal file
35
app/Library/getid3/getid3/getid3.lib.php
Executable file → Normal file
|
@ -414,6 +414,20 @@ class getid3_lib
|
||||||
return $newarray;
|
return $newarray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function flipped_array_merge_noclobber($array1, $array2) {
|
||||||
|
if (!is_array($array1) || !is_array($array2)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
# naturally, this only works non-recursively
|
||||||
|
$newarray = array_flip($array1);
|
||||||
|
foreach (array_flip($array2) as $key => $val) {
|
||||||
|
if (!isset($newarray[$key])) {
|
||||||
|
$newarray[$key] = count($newarray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return array_flip($newarray);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static function ksort_recursive(&$theArray) {
|
public static function ksort_recursive(&$theArray) {
|
||||||
ksort($theArray);
|
ksort($theArray);
|
||||||
|
@ -606,7 +620,7 @@ class getid3_lib
|
||||||
|
|
||||||
if (empty($tempdir)) {
|
if (empty($tempdir)) {
|
||||||
// yes this is ugly, feel free to suggest a better way
|
// yes this is ugly, feel free to suggest a better way
|
||||||
require_once(dirname(__FILE__) . '/getid3.php');
|
require_once(dirname(__FILE__).'/getid3.php');
|
||||||
$getid3_temp = new getID3();
|
$getid3_temp = new getID3();
|
||||||
$tempdir = $getid3_temp->tempdir;
|
$tempdir = $getid3_temp->tempdir;
|
||||||
unset($getid3_temp);
|
unset($getid3_temp);
|
||||||
|
@ -1153,11 +1167,19 @@ class getid3_lib
|
||||||
public static function GetDataImageSize($imgData, &$imageinfo=array()) {
|
public static function GetDataImageSize($imgData, &$imageinfo=array()) {
|
||||||
static $tempdir = '';
|
static $tempdir = '';
|
||||||
if (empty($tempdir)) {
|
if (empty($tempdir)) {
|
||||||
|
if (function_exists('sys_get_temp_dir')) {
|
||||||
|
$tempdir = sys_get_temp_dir(); // https://github.com/JamesHeinrich/getID3/issues/52
|
||||||
|
}
|
||||||
|
|
||||||
// yes this is ugly, feel free to suggest a better way
|
// yes this is ugly, feel free to suggest a better way
|
||||||
require_once(dirname(__FILE__) . '/getid3.php');
|
if (include_once(dirname(__FILE__).'/getid3.php')) {
|
||||||
$getid3_temp = new getID3();
|
if ($getid3_temp = new getID3()) {
|
||||||
$tempdir = $getid3_temp->tempdir;
|
if ($getid3_temp_tempdir = $getid3_temp->tempdir) {
|
||||||
unset($getid3_temp);
|
$tempdir = $getid3_temp_tempdir;
|
||||||
|
}
|
||||||
|
unset($getid3_temp, $getid3_temp_tempdir);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$GetDataImageSize = false;
|
$GetDataImageSize = false;
|
||||||
if ($tempfilename = tempnam($tempdir, 'gI3')) {
|
if ($tempfilename = tempnam($tempdir, 'gI3')) {
|
||||||
|
@ -1165,6 +1187,9 @@ class getid3_lib
|
||||||
fwrite($tmp, $imgData);
|
fwrite($tmp, $imgData);
|
||||||
fclose($tmp);
|
fclose($tmp);
|
||||||
$GetDataImageSize = @getimagesize($tempfilename, $imageinfo);
|
$GetDataImageSize = @getimagesize($tempfilename, $imageinfo);
|
||||||
|
if (($GetDataImageSize === false) || !isset($GetDataImageSize[0]) || !isset($GetDataImageSize[1])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
$GetDataImageSize['height'] = $GetDataImageSize[0];
|
$GetDataImageSize['height'] = $GetDataImageSize[0];
|
||||||
$GetDataImageSize['width'] = $GetDataImageSize[1];
|
$GetDataImageSize['width'] = $GetDataImageSize[1];
|
||||||
}
|
}
|
||||||
|
|
39
app/Library/getid3/getid3/getid3.php
Executable file → Normal file
39
app/Library/getid3/getid3/getid3.php
Executable file → Normal file
|
@ -109,7 +109,7 @@ class getID3
|
||||||
protected $startup_error = '';
|
protected $startup_error = '';
|
||||||
protected $startup_warning = '';
|
protected $startup_warning = '';
|
||||||
|
|
||||||
const VERSION = '1.9.9-20141121';
|
const VERSION = '1.9.10-201511241457';
|
||||||
const FREAD_BUFFER_SIZE = 32768;
|
const FREAD_BUFFER_SIZE = 32768;
|
||||||
|
|
||||||
const ATTACHMENTS_NONE = false;
|
const ATTACHMENTS_NONE = false;
|
||||||
|
@ -166,7 +166,7 @@ class getID3
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load support library
|
// Load support library
|
||||||
if (!include_once(GETID3_INCLUDEPATH . 'getid3.lib.php')) {
|
if (!include_once(GETID3_INCLUDEPATH.'getid3.lib.php')) {
|
||||||
$this->startup_error .= 'getid3.lib.php is missing or corrupt';
|
$this->startup_error .= 'getid3.lib.php is missing or corrupt';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +243,7 @@ class getID3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function openfile($filename) {
|
public function openfile($filename, $filesize=null) {
|
||||||
try {
|
try {
|
||||||
if (!empty($this->startup_error)) {
|
if (!empty($this->startup_error)) {
|
||||||
throw new getid3_exception($this->startup_error);
|
throw new getid3_exception($this->startup_error);
|
||||||
|
@ -287,7 +287,7 @@ class getID3
|
||||||
throw new getid3_exception('Could not open "'.$filename.'" ('.implode('; ', $errormessagelist).')');
|
throw new getid3_exception('Could not open "'.$filename.'" ('.implode('; ', $errormessagelist).')');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->info['filesize'] = filesize($filename);
|
$this->info['filesize'] = (!is_null($filesize) ? $filesize : filesize($filename));
|
||||||
// set redundant parameters - might be needed in some include file
|
// set redundant parameters - might be needed in some include file
|
||||||
// filenames / filepaths in getID3 are always expressed with forward slashes (unix-style) for both Windows and other to try and minimize confusion
|
// filenames / filepaths in getID3 are always expressed with forward slashes (unix-style) for both Windows and other to try and minimize confusion
|
||||||
$filename = str_replace('\\', '/', $filename);
|
$filename = str_replace('\\', '/', $filename);
|
||||||
|
@ -342,9 +342,9 @@ class getID3
|
||||||
}
|
}
|
||||||
|
|
||||||
// public: analyze file
|
// public: analyze file
|
||||||
public function analyze($filename) {
|
public function analyze($filename, $filesize=null, $original_filename='') {
|
||||||
try {
|
try {
|
||||||
if (!$this->openfile($filename)) {
|
if (!$this->openfile($filename, $filesize)) {
|
||||||
return $this->info;
|
return $this->info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,7 +389,7 @@ class getID3
|
||||||
$formattest = fread($this->fp, 32774);
|
$formattest = fread($this->fp, 32774);
|
||||||
|
|
||||||
// determine format
|
// determine format
|
||||||
$determined_format = $this->GetFileFormat($formattest, $filename);
|
$determined_format = $this->GetFileFormat($formattest, ($original_filename ? $original_filename : $filename));
|
||||||
|
|
||||||
// unable to determine file format
|
// unable to determine file format
|
||||||
if (!$determined_format) {
|
if (!$determined_format) {
|
||||||
|
@ -876,7 +876,7 @@ class getID3
|
||||||
'pattern' => '^(RIFF|SDSS|FORM)',
|
'pattern' => '^(RIFF|SDSS|FORM)',
|
||||||
'group' => 'audio-video',
|
'group' => 'audio-video',
|
||||||
'module' => 'riff',
|
'module' => 'riff',
|
||||||
'mime_type' => 'audio/x-wave',
|
'mime_type' => 'audio/x-wav',
|
||||||
'fail_ape' => 'WARNING',
|
'fail_ape' => 'WARNING',
|
||||||
),
|
),
|
||||||
|
|
||||||
|
@ -1235,6 +1235,29 @@ class getID3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ID3v1 encoding detection hack start
|
||||||
|
// ID3v1 is defined as always using ISO-8859-1 encoding, but it is not uncommon to find files tagged with ID3v1 using Windows-1251 or other character sets
|
||||||
|
// Since ID3v1 has no concept of character sets there is no certain way to know we have the correct non-ISO-8859-1 character set, but we can guess
|
||||||
|
if ($comment_name == 'id3v1') {
|
||||||
|
if ($encoding == 'ISO-8859-1') {
|
||||||
|
if (function_exists('iconv')) {
|
||||||
|
foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) {
|
||||||
|
foreach ($valuearray as $key => $value) {
|
||||||
|
if (preg_match('#^[\\x80-\\xFF]+$#', $value)) {
|
||||||
|
foreach (array('windows-1251', 'KOI8-R') as $id3v1_bad_encoding) {
|
||||||
|
if (@iconv($id3v1_bad_encoding, $id3v1_bad_encoding, $value) === $value) {
|
||||||
|
$encoding = $id3v1_bad_encoding;
|
||||||
|
break 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ID3v1 encoding detection hack end
|
||||||
|
|
||||||
$this->CharConvert($this->info['tags'][$tag_name], $encoding); // only copy gets converted!
|
$this->CharConvert($this->info['tags'][$tag_name], $encoding); // only copy gets converted!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
0
app/Library/getid3/getid3/module.archive.gzip.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.archive.gzip.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.archive.rar.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.archive.rar.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.archive.szip.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.archive.szip.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.archive.tar.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.archive.tar.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.archive.zip.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.archive.zip.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio-video.asf.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio-video.asf.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio-video.bink.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio-video.bink.php
Executable file → Normal file
2
app/Library/getid3/getid3/module.audio-video.flv.php
Executable file → Normal file
2
app/Library/getid3/getid3/module.audio-video.flv.php
Executable file → Normal file
|
@ -541,7 +541,7 @@ class AMFReader {
|
||||||
// Long string
|
// Long string
|
||||||
default:
|
default:
|
||||||
$value = '(unknown or unsupported data type)';
|
$value = '(unknown or unsupported data type)';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $value;
|
return $value;
|
||||||
|
|
33
app/Library/getid3/getid3/module.audio-video.matroska.php
Executable file → Normal file
33
app/Library/getid3/getid3/module.audio-video.matroska.php
Executable file → Normal file
|
@ -457,6 +457,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->warning('Unhandled audio type "'.(isset($trackarray['CodecID']) ? $trackarray['CodecID'] : '').'"');
|
$this->warning('Unhandled audio type "'.(isset($trackarray['CodecID']) ? $trackarray['CodecID'] : '').'"');
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$info['audio']['streams'][] = $track_info;
|
$info['audio']['streams'][] = $track_info;
|
||||||
|
@ -524,6 +525,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('header', __LINE__, $element_data);
|
$this->unhandledElement('header', __LINE__, $element_data);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
unset($element_data['offset'], $element_data['end']);
|
unset($element_data['offset'], $element_data['end']);
|
||||||
|
@ -562,6 +564,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('seekhead.seek', __LINE__, $sub_seek_entry); }
|
$this->unhandledElement('seekhead.seek', __LINE__, $sub_seek_entry); }
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($seek_entry['target_id'] != EBML_ID_CLUSTER || !self::$hide_clusters) { // collect clusters only if required
|
if ($seek_entry['target_id'] != EBML_ID_CLUSTER || !self::$hide_clusters) { // collect clusters only if required
|
||||||
|
@ -571,6 +574,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('seekhead', __LINE__, $seek_entry);
|
$this->unhandledElement('seekhead', __LINE__, $seek_entry);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -653,6 +657,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('track.video', __LINE__, $sub_subelement);
|
$this->unhandledElement('track.video', __LINE__, $sub_subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -678,6 +683,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('track.audio', __LINE__, $sub_subelement);
|
$this->unhandledElement('track.audio', __LINE__, $sub_subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -713,6 +719,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement);
|
$this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -736,24 +743,28 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement);
|
$this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('track.contentencodings.contentencoding', __LINE__, $sub_sub_subelement);
|
$this->unhandledElement('track.contentencodings.contentencoding', __LINE__, $sub_sub_subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('track.contentencodings', __LINE__, $sub_subelement);
|
$this->unhandledElement('track.contentencodings', __LINE__, $sub_subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('track', __LINE__, $subelement);
|
$this->unhandledElement('track', __LINE__, $subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -762,6 +773,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('tracks', __LINE__, $track_entry);
|
$this->unhandledElement('tracks', __LINE__, $track_entry);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -825,6 +837,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('info.chaptertranslate', __LINE__, $sub_subelement);
|
$this->unhandledElement('info.chaptertranslate', __LINE__, $sub_subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$info_entry[$subelement['id_name']] = $chaptertranslate_entry;
|
$info_entry[$subelement['id_name']] = $chaptertranslate_entry;
|
||||||
|
@ -832,6 +845,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('info', __LINE__, $subelement);
|
$this->unhandledElement('info', __LINE__, $subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$info['matroska']['info'][] = $info_entry;
|
$info['matroska']['info'][] = $info_entry;
|
||||||
|
@ -868,6 +882,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('cues.cuepoint.cuetrackpositions', __LINE__, $sub_sub_subelement);
|
$this->unhandledElement('cues.cuepoint.cuetrackpositions', __LINE__, $sub_sub_subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$cuepoint_entry[$sub_subelement['id_name']][] = $cuetrackpositions_entry;
|
$cuepoint_entry[$sub_subelement['id_name']][] = $cuetrackpositions_entry;
|
||||||
|
@ -879,6 +894,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('cues.cuepoint', __LINE__, $sub_subelement);
|
$this->unhandledElement('cues.cuepoint', __LINE__, $sub_subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$cues_entry[] = $cuepoint_entry;
|
$cues_entry[] = $cuepoint_entry;
|
||||||
|
@ -886,6 +902,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('cues', __LINE__, $subelement);
|
$this->unhandledElement('cues', __LINE__, $subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$info['matroska']['cues'] = $cues_entry;
|
$info['matroska']['cues'] = $cues_entry;
|
||||||
|
@ -927,6 +944,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('tags.tag.targets', __LINE__, $sub_sub_subelement);
|
$this->unhandledElement('tags.tag.targets', __LINE__, $sub_sub_subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$tag_entry[$sub_subelement['id_name']] = $targets_entry;
|
$tag_entry[$sub_subelement['id_name']] = $targets_entry;
|
||||||
|
@ -938,6 +956,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('tags.tag', __LINE__, $sub_subelement);
|
$this->unhandledElement('tags.tag', __LINE__, $sub_subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$tags_entry[] = $tag_entry;
|
$tags_entry[] = $tag_entry;
|
||||||
|
@ -945,6 +964,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('tags', __LINE__, $subelement);
|
$this->unhandledElement('tags', __LINE__, $subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$info['matroska']['tags'] = $tags_entry;
|
$info['matroska']['tags'] = $tags_entry;
|
||||||
|
@ -985,6 +1005,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('attachments.attachedfile', __LINE__, $sub_subelement);
|
$this->unhandledElement('attachments.attachedfile', __LINE__, $sub_subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$info['matroska']['attachments'][] = $attachedfile_entry;
|
$info['matroska']['attachments'][] = $attachedfile_entry;
|
||||||
|
@ -992,6 +1013,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('attachments', __LINE__, $subelement);
|
$this->unhandledElement('attachments', __LINE__, $subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1051,6 +1073,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('chapters.editionentry.chapteratom.chaptertrack', __LINE__, $sub_sub_sub_subelement);
|
$this->unhandledElement('chapters.editionentry.chapteratom.chaptertrack', __LINE__, $sub_sub_sub_subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$chapteratom_entry[$sub_sub_subelement['id_name']][] = $chaptertrack_entry;
|
$chapteratom_entry[$sub_sub_subelement['id_name']][] = $chaptertrack_entry;
|
||||||
|
@ -1070,6 +1093,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('chapters.editionentry.chapteratom.chapterdisplay', __LINE__, $sub_sub_sub_subelement);
|
$this->unhandledElement('chapters.editionentry.chapteratom.chapterdisplay', __LINE__, $sub_sub_sub_subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$chapteratom_entry[$sub_sub_subelement['id_name']][] = $chapterdisplay_entry;
|
$chapteratom_entry[$sub_sub_subelement['id_name']][] = $chapterdisplay_entry;
|
||||||
|
@ -1077,6 +1101,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('chapters.editionentry.chapteratom', __LINE__, $sub_sub_subelement);
|
$this->unhandledElement('chapters.editionentry.chapteratom', __LINE__, $sub_sub_subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$editionentry_entry[$sub_subelement['id_name']][] = $chapteratom_entry;
|
$editionentry_entry[$sub_subelement['id_name']][] = $chapteratom_entry;
|
||||||
|
@ -1084,6 +1109,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('chapters.editionentry', __LINE__, $sub_subelement);
|
$this->unhandledElement('chapters.editionentry', __LINE__, $sub_subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$info['matroska']['chapters'][] = $editionentry_entry;
|
$info['matroska']['chapters'][] = $editionentry_entry;
|
||||||
|
@ -1091,6 +1117,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('chapters', __LINE__, $subelement);
|
$this->unhandledElement('chapters', __LINE__, $subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1119,6 +1146,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('cluster.silenttracks', __LINE__, $sub_subelement);
|
$this->unhandledElement('cluster.silenttracks', __LINE__, $sub_subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$cluster_entry[$subelement['id_name']][] = $cluster_silent_tracks;
|
$cluster_entry[$subelement['id_name']][] = $cluster_silent_tracks;
|
||||||
|
@ -1149,6 +1177,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('clusters.blockgroup', __LINE__, $sub_subelement);
|
$this->unhandledElement('clusters.blockgroup', __LINE__, $sub_subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$cluster_entry[$subelement['id_name']][] = $cluster_block_group;
|
$cluster_entry[$subelement['id_name']][] = $cluster_block_group;
|
||||||
|
@ -1160,6 +1189,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('cluster', __LINE__, $subelement);
|
$this->unhandledElement('cluster', __LINE__, $subelement);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
$this->current_offset = $subelement['end'];
|
$this->current_offset = $subelement['end'];
|
||||||
}
|
}
|
||||||
|
@ -1181,12 +1211,14 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('segment', __LINE__, $element_data);
|
$this->unhandledElement('segment', __LINE__, $element_data);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('root', __LINE__, $top_element);
|
$this->unhandledElement('root', __LINE__, $top_element);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1339,6 +1371,7 @@ class getid3_matroska extends getid3_handler
|
||||||
|
|
||||||
default:
|
default:
|
||||||
$this->unhandledElement('tag.simpletag', __LINE__, $element);
|
$this->unhandledElement('tag.simpletag', __LINE__, $element);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
0
app/Library/getid3/getid3/module.audio-video.mpeg.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio-video.mpeg.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio-video.nsv.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio-video.nsv.php
Executable file → Normal file
563
app/Library/getid3/getid3/module.audio-video.quicktime.php
Executable file → Normal file
563
app/Library/getid3/getid3/module.audio-video.quicktime.php
Executable file → Normal file
|
@ -81,6 +81,81 @@ class getid3_quicktime extends getid3_handler
|
||||||
unset($info['avdataend_tmp']);
|
unset($info['avdataend_tmp']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!empty($info['quicktime']['comments']['chapters']) && is_array($info['quicktime']['comments']['chapters']) && (count($info['quicktime']['comments']['chapters']) > 0)) {
|
||||||
|
$durations = $this->quicktime_time_to_sample_table($info);
|
||||||
|
for ($i = 0; $i < count($info['quicktime']['comments']['chapters']); $i++) {
|
||||||
|
$bookmark = array();
|
||||||
|
$bookmark['title'] = $info['quicktime']['comments']['chapters'][$i];
|
||||||
|
if (isset($durations[$i])) {
|
||||||
|
$bookmark['duration_sample'] = $durations[$i]['sample_duration'];
|
||||||
|
if ($i > 0) {
|
||||||
|
$bookmark['start_sample'] = $info['quicktime']['bookmarks'][($i - 1)]['start_sample'] + $info['quicktime']['bookmarks'][($i - 1)]['duration_sample'];
|
||||||
|
} else {
|
||||||
|
$bookmark['start_sample'] = 0;
|
||||||
|
}
|
||||||
|
if ($time_scale = $this->quicktime_bookmark_time_scale($info)) {
|
||||||
|
$bookmark['duration_seconds'] = $bookmark['duration_sample'] / $time_scale;
|
||||||
|
$bookmark['start_seconds'] = $bookmark['start_sample'] / $time_scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$info['quicktime']['bookmarks'][] = $bookmark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($info['quicktime']['temp_meta_key_names'])) {
|
||||||
|
unset($info['quicktime']['temp_meta_key_names']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($info['quicktime']['comments']['location.ISO6709'])) {
|
||||||
|
// https://en.wikipedia.org/wiki/ISO_6709
|
||||||
|
foreach ($info['quicktime']['comments']['location.ISO6709'] as $ISO6709string) {
|
||||||
|
$latitude = false;
|
||||||
|
$longitude = false;
|
||||||
|
$altitude = false;
|
||||||
|
if (preg_match('#^([\\+\\-])([0-9]{2}|[0-9]{4}|[0-9]{6})(\\.[0-9]+)?([\\+\\-])([0-9]{3}|[0-9]{5}|[0-9]{7})(\\.[0-9]+)?(([\\+\\-])([0-9]{3}|[0-9]{5}|[0-9]{7})(\\.[0-9]+)?)?/$#', $ISO6709string, $matches)) {
|
||||||
|
@list($dummy, $lat_sign, $lat_deg, $lat_deg_dec, $lon_sign, $lon_deg, $lon_deg_dec, $dummy, $alt_sign, $alt_deg, $alt_deg_dec) = $matches;
|
||||||
|
|
||||||
|
if (strlen($lat_deg) == 2) { // [+-]DD.D
|
||||||
|
$latitude = floatval(ltrim($lat_deg, '0').$lat_deg_dec);
|
||||||
|
} elseif (strlen($lat_deg) == 4) { // [+-]DDMM.M
|
||||||
|
$latitude = floatval(ltrim(substr($lat_deg, 0, 2), '0')) + floatval(ltrim(substr($lat_deg, 2, 2), '0').$lat_deg_dec / 60);
|
||||||
|
} elseif (strlen($lat_deg) == 6) { // [+-]DDMMSS.S
|
||||||
|
$latitude = floatval(ltrim(substr($lat_deg, 0, 2), '0')) + floatval(ltrim(substr($lat_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($lat_deg, 4, 2), '0').$lat_deg_dec / 3600);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen($lon_deg) == 3) { // [+-]DDD.D
|
||||||
|
$longitude = floatval(ltrim($lon_deg, '0').$lon_deg_dec);
|
||||||
|
} elseif (strlen($lon_deg) == 5) { // [+-]DDDMM.M
|
||||||
|
$longitude = floatval(ltrim(substr($lon_deg, 0, 2), '0')) + floatval(ltrim(substr($lon_deg, 2, 2), '0').$lon_deg_dec / 60);
|
||||||
|
} elseif (strlen($lon_deg) == 7) { // [+-]DDDMMSS.S
|
||||||
|
$longitude = floatval(ltrim(substr($lon_deg, 0, 2), '0')) + floatval(ltrim(substr($lon_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($lon_deg, 4, 2), '0').$lon_deg_dec / 3600);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen($alt_deg) == 3) { // [+-]DDD.D
|
||||||
|
$altitude = floatval(ltrim($alt_deg, '0').$alt_deg_dec);
|
||||||
|
} elseif (strlen($alt_deg) == 5) { // [+-]DDDMM.M
|
||||||
|
$altitude = floatval(ltrim(substr($alt_deg, 0, 2), '0')) + floatval(ltrim(substr($alt_deg, 2, 2), '0').$alt_deg_dec / 60);
|
||||||
|
} elseif (strlen($alt_deg) == 7) { // [+-]DDDMMSS.S
|
||||||
|
$altitude = floatval(ltrim(substr($alt_deg, 0, 2), '0')) + floatval(ltrim(substr($alt_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($alt_deg, 4, 2), '0').$alt_deg_dec / 3600);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($latitude !== false) {
|
||||||
|
$info['quicktime']['comments']['gps_latitude'][] = (($lat_sign == '-') ? -1 : 1) * floatval($latitude);
|
||||||
|
}
|
||||||
|
if ($longitude !== false) {
|
||||||
|
$info['quicktime']['comments']['gps_longitude'][] = (($lon_sign == '-') ? -1 : 1) * floatval($longitude);
|
||||||
|
}
|
||||||
|
if ($altitude !== false) {
|
||||||
|
$info['quicktime']['comments']['gps_altitude'][] = (($alt_sign == '-') ? -1 : 1) * floatval($altitude);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($latitude === false) {
|
||||||
|
$info['warning'][] = 'location.ISO6709 string not parsed correctly: "'.$ISO6709string.'", please submit as a bug';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!isset($info['bitrate']) && isset($info['playtime_seconds'])) {
|
if (!isset($info['bitrate']) && isset($info['playtime_seconds'])) {
|
||||||
$info['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
|
$info['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
|
||||||
}
|
}
|
||||||
|
@ -120,6 +195,7 @@ class getid3_quicktime extends getid3_handler
|
||||||
|
|
||||||
public function QuicktimeParseAtom($atomname, $atomsize, $atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) {
|
public function QuicktimeParseAtom($atomname, $atomsize, $atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) {
|
||||||
// http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm
|
// http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm
|
||||||
|
// https://code.google.com/p/mp4v2/wiki/iTunesMetadata
|
||||||
|
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
|
@ -222,81 +298,88 @@ class getid3_quicktime extends getid3_handler
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case "\xA9".'alb': // ALBum
|
||||||
|
case "\xA9".'ART': //
|
||||||
|
case "\xA9".'art': // ARTist
|
||||||
|
case "\xA9".'aut': //
|
||||||
|
case "\xA9".'cmt': // CoMmenT
|
||||||
|
case "\xA9".'com': // COMposer
|
||||||
|
case "\xA9".'cpy': //
|
||||||
|
case "\xA9".'day': // content created year
|
||||||
|
case "\xA9".'dir': //
|
||||||
|
case "\xA9".'ed1': //
|
||||||
|
case "\xA9".'ed2': //
|
||||||
|
case "\xA9".'ed3': //
|
||||||
|
case "\xA9".'ed4': //
|
||||||
|
case "\xA9".'ed5': //
|
||||||
|
case "\xA9".'ed6': //
|
||||||
|
case "\xA9".'ed7': //
|
||||||
|
case "\xA9".'ed8': //
|
||||||
|
case "\xA9".'ed9': //
|
||||||
|
case "\xA9".'enc': //
|
||||||
|
case "\xA9".'fmt': //
|
||||||
|
case "\xA9".'gen': // GENre
|
||||||
|
case "\xA9".'grp': // GRouPing
|
||||||
|
case "\xA9".'hst': //
|
||||||
|
case "\xA9".'inf': //
|
||||||
|
case "\xA9".'lyr': // LYRics
|
||||||
|
case "\xA9".'mak': //
|
||||||
|
case "\xA9".'mod': //
|
||||||
|
case "\xA9".'nam': // full NAMe
|
||||||
|
case "\xA9".'ope': //
|
||||||
|
case "\xA9".'PRD': //
|
||||||
|
case "\xA9".'prf': //
|
||||||
|
case "\xA9".'req': //
|
||||||
|
case "\xA9".'src': //
|
||||||
|
case "\xA9".'swr': //
|
||||||
|
case "\xA9".'too': // encoder
|
||||||
|
case "\xA9".'trk': // TRacK
|
||||||
|
case "\xA9".'url': //
|
||||||
|
case "\xA9".'wrn': //
|
||||||
|
case "\xA9".'wrt': // WRiTer
|
||||||
|
case '----': // itunes specific
|
||||||
case 'aART': // Album ARTist
|
case 'aART': // Album ARTist
|
||||||
|
case 'akID': // iTunes store account type
|
||||||
|
case 'apID': // Purchase Account
|
||||||
|
case 'atID': //
|
||||||
case 'catg': // CaTeGory
|
case 'catg': // CaTeGory
|
||||||
|
case 'cmID': //
|
||||||
|
case 'cnID': //
|
||||||
case 'covr': // COVeR artwork
|
case 'covr': // COVeR artwork
|
||||||
case 'cpil': // ComPILation
|
case 'cpil': // ComPILation
|
||||||
case 'cprt': // CoPyRighT
|
case 'cprt': // CoPyRighT
|
||||||
case 'desc': // DESCription
|
case 'desc': // DESCription
|
||||||
case 'disk': // DISK number
|
case 'disk': // DISK number
|
||||||
case 'egid': // Episode Global ID
|
case 'egid': // Episode Global ID
|
||||||
|
case 'geID': //
|
||||||
case 'gnre': // GeNRE
|
case 'gnre': // GeNRE
|
||||||
|
case 'hdvd': // HD ViDeo
|
||||||
case 'keyw': // KEYWord
|
case 'keyw': // KEYWord
|
||||||
case 'ldes':
|
case 'ldes': // Long DEScription
|
||||||
case 'pcst': // PodCaST
|
case 'pcst': // PodCaST
|
||||||
case 'pgap': // GAPless Playback
|
case 'pgap': // GAPless Playback
|
||||||
|
case 'plID': //
|
||||||
case 'purd': // PURchase Date
|
case 'purd': // PURchase Date
|
||||||
case 'purl': // Podcast URL
|
case 'purl': // Podcast URL
|
||||||
case 'rati':
|
case 'rati': //
|
||||||
case 'rndu':
|
case 'rndu': //
|
||||||
case 'rpdu':
|
case 'rpdu': //
|
||||||
case 'rtng': // RaTiNG
|
case 'rtng': // RaTiNG
|
||||||
case 'stik':
|
case 'sfID': // iTunes store country
|
||||||
|
case 'soaa': // SOrt Album Artist
|
||||||
|
case 'soal': // SOrt ALbum
|
||||||
|
case 'soar': // SOrt ARtist
|
||||||
|
case 'soco': // SOrt COmposer
|
||||||
|
case 'sonm': // SOrt NaMe
|
||||||
|
case 'sosn': // SOrt Show Name
|
||||||
|
case 'stik': //
|
||||||
case 'tmpo': // TeMPO (BPM)
|
case 'tmpo': // TeMPO (BPM)
|
||||||
case 'trkn': // TRacK Number
|
case 'trkn': // TRacK Number
|
||||||
|
case 'tven': // tvEpisodeID
|
||||||
case 'tves': // TV EpiSode
|
case 'tves': // TV EpiSode
|
||||||
case 'tvnn': // TV Network Name
|
case 'tvnn': // TV Network Name
|
||||||
case 'tvsh': // TV SHow Name
|
case 'tvsh': // TV SHow Name
|
||||||
case 'tvsn': // TV SeasoN
|
case 'tvsn': // TV SeasoN
|
||||||
case 'akID': // iTunes store account type
|
|
||||||
case 'apID':
|
|
||||||
case 'atID':
|
|
||||||
case 'cmID':
|
|
||||||
case 'cnID':
|
|
||||||
case 'geID':
|
|
||||||
case 'plID':
|
|
||||||
case 'sfID': // iTunes store country
|
|
||||||
case "\xA9".'alb': // ALBum
|
|
||||||
case "\xA9".'art': // ARTist
|
|
||||||
case "\xA9".'ART':
|
|
||||||
case "\xA9".'aut':
|
|
||||||
case "\xA9".'cmt': // CoMmenT
|
|
||||||
case "\xA9".'com': // COMposer
|
|
||||||
case "\xA9".'cpy':
|
|
||||||
case "\xA9".'day': // content created year
|
|
||||||
case "\xA9".'dir':
|
|
||||||
case "\xA9".'ed1':
|
|
||||||
case "\xA9".'ed2':
|
|
||||||
case "\xA9".'ed3':
|
|
||||||
case "\xA9".'ed4':
|
|
||||||
case "\xA9".'ed5':
|
|
||||||
case "\xA9".'ed6':
|
|
||||||
case "\xA9".'ed7':
|
|
||||||
case "\xA9".'ed8':
|
|
||||||
case "\xA9".'ed9':
|
|
||||||
case "\xA9".'enc':
|
|
||||||
case "\xA9".'fmt':
|
|
||||||
case "\xA9".'gen': // GENre
|
|
||||||
case "\xA9".'grp': // GRouPing
|
|
||||||
case "\xA9".'hst':
|
|
||||||
case "\xA9".'inf':
|
|
||||||
case "\xA9".'lyr': // LYRics
|
|
||||||
case "\xA9".'mak':
|
|
||||||
case "\xA9".'mod':
|
|
||||||
case "\xA9".'nam': // full NAMe
|
|
||||||
case "\xA9".'ope':
|
|
||||||
case "\xA9".'PRD':
|
|
||||||
case "\xA9".'prd':
|
|
||||||
case "\xA9".'prf':
|
|
||||||
case "\xA9".'req':
|
|
||||||
case "\xA9".'src':
|
|
||||||
case "\xA9".'swr':
|
|
||||||
case "\xA9".'too': // encoder
|
|
||||||
case "\xA9".'trk': // TRacK
|
|
||||||
case "\xA9".'url':
|
|
||||||
case "\xA9".'wrn':
|
|
||||||
case "\xA9".'wrt': // WRiTer
|
|
||||||
case '----': // itunes specific
|
|
||||||
if ($atom_parent == 'udta') {
|
if ($atom_parent == 'udta') {
|
||||||
// User data atom handler
|
// User data atom handler
|
||||||
$atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
|
$atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
|
||||||
|
@ -361,17 +444,21 @@ class getid3_quicktime extends getid3_handler
|
||||||
case 21: // tmpo/cpil flag
|
case 21: // tmpo/cpil flag
|
||||||
switch ($atomname) {
|
switch ($atomname) {
|
||||||
case 'cpil':
|
case 'cpil':
|
||||||
|
case 'hdvd':
|
||||||
case 'pcst':
|
case 'pcst':
|
||||||
case 'pgap':
|
case 'pgap':
|
||||||
|
// 8-bit integer (boolean)
|
||||||
$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
|
$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'tmpo':
|
case 'tmpo':
|
||||||
|
// 16-bit integer
|
||||||
$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 2));
|
$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 2));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'disk':
|
case 'disk':
|
||||||
case 'trkn':
|
case 'trkn':
|
||||||
|
// binary
|
||||||
$num = getid3_lib::BigEndian2Int(substr($boxdata, 10, 2));
|
$num = getid3_lib::BigEndian2Int(substr($boxdata, 10, 2));
|
||||||
$num_total = getid3_lib::BigEndian2Int(substr($boxdata, 12, 2));
|
$num_total = getid3_lib::BigEndian2Int(substr($boxdata, 12, 2));
|
||||||
$atom_structure['data'] = empty($num) ? '' : $num;
|
$atom_structure['data'] = empty($num) ? '' : $num;
|
||||||
|
@ -379,21 +466,25 @@ class getid3_quicktime extends getid3_handler
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'gnre':
|
case 'gnre':
|
||||||
|
// enum
|
||||||
$GenreID = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
|
$GenreID = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
|
||||||
$atom_structure['data'] = getid3_id3v1::LookupGenreName($GenreID - 1);
|
$atom_structure['data'] = getid3_id3v1::LookupGenreName($GenreID - 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'rtng':
|
case 'rtng':
|
||||||
|
// 8-bit integer
|
||||||
$atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
|
$atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
|
||||||
$atom_structure['data'] = $this->QuicktimeContentRatingLookup($atom_structure[$atomname]);
|
$atom_structure['data'] = $this->QuicktimeContentRatingLookup($atom_structure[$atomname]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'stik':
|
case 'stik':
|
||||||
|
// 8-bit integer (enum)
|
||||||
$atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
|
$atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
|
||||||
$atom_structure['data'] = $this->QuicktimeSTIKLookup($atom_structure[$atomname]);
|
$atom_structure['data'] = $this->QuicktimeSTIKLookup($atom_structure[$atomname]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'sfID':
|
case 'sfID':
|
||||||
|
// 32-bit integer
|
||||||
$atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
|
$atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
|
||||||
$atom_structure['data'] = $this->QuicktimeStoreFrontCodeLookup($atom_structure[$atomname]);
|
$atom_structure['data'] = $this->QuicktimeStoreFrontCodeLookup($atom_structure[$atomname]);
|
||||||
break;
|
break;
|
||||||
|
@ -403,7 +494,18 @@ class getid3_quicktime extends getid3_handler
|
||||||
$atom_structure['data'] = substr($boxdata, 8);
|
$atom_structure['data'] = substr($boxdata, 8);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'plID':
|
||||||
|
// 64-bit integer
|
||||||
|
$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 8));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'atID':
|
||||||
|
case 'cnID':
|
||||||
|
case 'geID':
|
||||||
|
case 'tves':
|
||||||
|
case 'tvsn':
|
||||||
default:
|
default:
|
||||||
|
// 32-bit integer
|
||||||
$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
|
$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -928,13 +1030,13 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
||||||
for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
|
for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
|
||||||
$atom_structure['data_references'][$i]['size'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 4));
|
$atom_structure['data_references'][$i]['size'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 4));
|
||||||
$drefDataOffset += 4;
|
$drefDataOffset += 4;
|
||||||
$atom_structure['data_references'][$i]['type'] = substr($atom_data, $drefDataOffset, 4);
|
$atom_structure['data_references'][$i]['type'] = substr($atom_data, $drefDataOffset, 4);
|
||||||
$drefDataOffset += 4;
|
$drefDataOffset += 4;
|
||||||
$atom_structure['data_references'][$i]['version'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 1));
|
$atom_structure['data_references'][$i]['version'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 1));
|
||||||
$drefDataOffset += 1;
|
$drefDataOffset += 1;
|
||||||
$atom_structure['data_references'][$i]['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 3)); // hardcoded: 0x0000
|
$atom_structure['data_references'][$i]['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 3)); // hardcoded: 0x0000
|
||||||
$drefDataOffset += 3;
|
$drefDataOffset += 3;
|
||||||
$atom_structure['data_references'][$i]['data'] = substr($atom_data, $drefDataOffset, ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3));
|
$atom_structure['data_references'][$i]['data'] = substr($atom_data, $drefDataOffset, ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3));
|
||||||
$drefDataOffset += ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3);
|
$drefDataOffset += ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3);
|
||||||
|
|
||||||
$atom_structure['data_references'][$i]['flags']['self_reference'] = (bool) ($atom_structure['data_references'][$i]['flags_raw'] & 0x001);
|
$atom_structure['data_references'][$i]['flags']['self_reference'] = (bool) ($atom_structure['data_references'][$i]['flags_raw'] & 0x001);
|
||||||
|
@ -1004,7 +1106,7 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
||||||
$info['error'][] = 'Corrupt Quicktime file: mdhd.time_scale == zero';
|
$info['error'][] = 'Corrupt Quicktime file: mdhd.time_scale == zero';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$info['quicktime']['time_scale'] = (isset($info['quicktime']['time_scale']) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);
|
$info['quicktime']['time_scale'] = ((isset($info['quicktime']['time_scale']) && ($info['quicktime']['time_scale'] < 1000)) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);
|
||||||
|
|
||||||
$atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
|
$atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
|
||||||
$atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
|
$atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
|
||||||
|
@ -1019,7 +1121,7 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
||||||
case 'pnot': // Preview atom
|
case 'pnot': // Preview atom
|
||||||
$atom_structure['modification_date'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); // "standard Macintosh format"
|
$atom_structure['modification_date'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); // "standard Macintosh format"
|
||||||
$atom_structure['version_number'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x00
|
$atom_structure['version_number'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x00
|
||||||
$atom_structure['atom_type'] = substr($atom_data, 6, 4); // usually: 'PICT'
|
$atom_structure['atom_type'] = substr($atom_data, 6, 4); // usually: 'PICT'
|
||||||
$atom_structure['atom_index'] = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2)); // usually: 0x01
|
$atom_structure['atom_index'] = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2)); // usually: 0x01
|
||||||
|
|
||||||
$atom_structure['modification_date_unix'] = getid3_lib::DateMac2Unix($atom_structure['modification_date']);
|
$atom_structure['modification_date_unix'] = getid3_lib::DateMac2Unix($atom_structure['modification_date']);
|
||||||
|
@ -1029,7 +1131,7 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
||||||
case 'crgn': // Clipping ReGioN atom
|
case 'crgn': // Clipping ReGioN atom
|
||||||
$atom_structure['region_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); // The Region size, Region boundary box,
|
$atom_structure['region_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); // The Region size, Region boundary box,
|
||||||
$atom_structure['boundary_box'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 8)); // and Clipping region data fields
|
$atom_structure['boundary_box'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 8)); // and Clipping region data fields
|
||||||
$atom_structure['clipping_data'] = substr($atom_data, 10); // constitute a QuickDraw region.
|
$atom_structure['clipping_data'] = substr($atom_data, 10); // constitute a QuickDraw region.
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1120,7 +1222,7 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
||||||
}
|
}
|
||||||
$atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
|
$atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
|
||||||
$atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
|
$atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
|
||||||
$info['quicktime']['time_scale'] = (isset($info['quicktime']['time_scale']) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);
|
$info['quicktime']['time_scale'] = ((isset($info['quicktime']['time_scale']) && ($info['quicktime']['time_scale'] < 1000)) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);
|
||||||
$info['quicktime']['display_scale'] = $atom_structure['matrix_a'];
|
$info['quicktime']['display_scale'] = $atom_structure['matrix_a'];
|
||||||
$info['playtime_seconds'] = $atom_structure['duration'] / $atom_structure['time_scale'];
|
$info['playtime_seconds'] = $atom_structure['duration'] / $atom_structure['time_scale'];
|
||||||
break;
|
break;
|
||||||
|
@ -1240,14 +1342,20 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
||||||
}
|
}
|
||||||
|
|
||||||
// check to see if it looks like chapter titles, in the form of unterminated strings with a leading 16-bit size field
|
// check to see if it looks like chapter titles, in the form of unterminated strings with a leading 16-bit size field
|
||||||
while (($chapter_string_length = getid3_lib::BigEndian2Int(substr($atom_data, $mdat_offset, 2)))
|
while (($mdat_offset < (strlen($atom_data) - 8))
|
||||||
|
&& ($chapter_string_length = getid3_lib::BigEndian2Int(substr($atom_data, $mdat_offset, 2)))
|
||||||
&& ($chapter_string_length < 1000)
|
&& ($chapter_string_length < 1000)
|
||||||
&& ($chapter_string_length <= (strlen($atom_data) - $mdat_offset - 2))
|
&& ($chapter_string_length <= (strlen($atom_data) - $mdat_offset - 2))
|
||||||
&& preg_match('#^[\x20-\xFF]+$#', substr($atom_data, $mdat_offset + 2, $chapter_string_length), $chapter_matches)) {
|
&& preg_match('#^([\x00-\xFF]{2})([\x20-\xFF]+)$#', substr($atom_data, $mdat_offset, $chapter_string_length + 2), $chapter_matches)) {
|
||||||
|
list($dummy, $chapter_string_length_hex, $chapter_string) = $chapter_matches;
|
||||||
$mdat_offset += (2 + $chapter_string_length);
|
$mdat_offset += (2 + $chapter_string_length);
|
||||||
@$info['quicktime']['comments']['chapters'][] = $chapter_matches[0];
|
@$info['quicktime']['comments']['chapters'][] = $chapter_string;
|
||||||
}
|
|
||||||
|
|
||||||
|
// "encd" atom specifies encoding. In theory could be anything, almost always UTF-8, but may be UTF-16 with BOM (not currently handled)
|
||||||
|
if (substr($atom_data, $mdat_offset, 12) == "\x00\x00\x00\x0C\x65\x6E\x63\x64\x00\x00\x01\x00") { // UTF-8
|
||||||
|
$mdat_offset += 12;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (($atomsize > 8) && (!isset($info['avdataend_tmp']) || ($info['quicktime'][$atomname]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) {
|
if (($atomsize > 8) && (!isset($info['avdataend_tmp']) || ($info['quicktime'][$atomname]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) {
|
||||||
|
@ -1397,22 +1505,53 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "\x00\x00\x00\x00":
|
case "\x00\x00\x00\x00":
|
||||||
case 'meta': // METAdata atom
|
|
||||||
// some kind of metacontainer, may contain a big data dump such as:
|
// some kind of metacontainer, may contain a big data dump such as:
|
||||||
// mdta keys \005 mdtacom.apple.quicktime.make (mdtacom.apple.quicktime.creationdate ,mdtacom.apple.quicktime.location.ISO6709 $mdtacom.apple.quicktime.software !mdtacom.apple.quicktime.model ilst \01D \001 \015data \001DE\010Apple 0 \002 (data \001DE\0102011-05-11T17:54:04+0200 2 \003 *data \001DE\010+52.4936+013.3897+040.247/ \01D \004 \015data \001DE\0104.3.1 \005 \018data \001DE\010iPhone 4
|
// mdta keys \005 mdtacom.apple.quicktime.make (mdtacom.apple.quicktime.creationdate ,mdtacom.apple.quicktime.location.ISO6709 $mdtacom.apple.quicktime.software !mdtacom.apple.quicktime.model ilst \01D \001 \015data \001DE\010Apple 0 \002 (data \001DE\0102011-05-11T17:54:04+0200 2 \003 *data \001DE\010+52.4936+013.3897+040.247/ \01D \004 \015data \001DE\0104.3.1 \005 \018data \001DE\010iPhone 4
|
||||||
// http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt
|
// http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt
|
||||||
|
|
||||||
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
||||||
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
|
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
|
||||||
$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom(substr($atom_data, 4), $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
|
$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom(substr($atom_data, 4), $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
|
||||||
//$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
|
//$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'meta': // METAdata atom
|
||||||
|
// https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
|
||||||
|
|
||||||
|
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
||||||
|
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
|
||||||
|
$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'data': // metaDATA atom
|
case 'data': // metaDATA atom
|
||||||
|
static $metaDATAkey = 1; // real ugly, but so is the QuickTime structure that stores keys and values in different multinested locations that are hard to relate to each other
|
||||||
// seems to be 2 bytes language code (ASCII), 2 bytes unknown (set to 0x10B5 in sample I have), remainder is useful data
|
// seems to be 2 bytes language code (ASCII), 2 bytes unknown (set to 0x10B5 in sample I have), remainder is useful data
|
||||||
$atom_structure['language'] = substr($atom_data, 4 + 0, 2);
|
$atom_structure['language'] = substr($atom_data, 4 + 0, 2);
|
||||||
$atom_structure['unknown'] = getid3_lib::BigEndian2Int(substr($atom_data, 4 + 2, 2));
|
$atom_structure['unknown'] = getid3_lib::BigEndian2Int(substr($atom_data, 4 + 2, 2));
|
||||||
$atom_structure['data'] = substr($atom_data, 4 + 4);
|
$atom_structure['data'] = substr($atom_data, 4 + 4);
|
||||||
|
$atom_structure['key_name'] = @$info['quicktime']['temp_meta_key_names'][$metaDATAkey++];
|
||||||
|
|
||||||
|
if ($atom_structure['key_name'] && $atom_structure['data']) {
|
||||||
|
@$info['quicktime']['comments'][str_replace('com.apple.quicktime.', '', $atom_structure['key_name'])][] = $atom_structure['data'];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'keys': // KEYS that may be present in the metadata atom.
|
||||||
|
// https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW21
|
||||||
|
// The metadata item keys atom holds a list of the metadata keys that may be present in the metadata atom.
|
||||||
|
// This list is indexed starting with 1; 0 is a reserved index value. The metadata item keys atom is a full atom with an atom type of "keys".
|
||||||
|
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
|
||||||
|
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
|
||||||
|
$atom_structure['entry_count'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
|
||||||
|
$keys_atom_offset = 8;
|
||||||
|
for ($i = 1; $i <= $atom_structure['entry_count']; $i++) {
|
||||||
|
$atom_structure['keys'][$i]['key_size'] = getid3_lib::BigEndian2Int(substr($atom_data, $keys_atom_offset + 0, 4));
|
||||||
|
$atom_structure['keys'][$i]['key_namespace'] = substr($atom_data, $keys_atom_offset + 4, 4);
|
||||||
|
$atom_structure['keys'][$i]['key_value'] = substr($atom_data, $keys_atom_offset + 8, $atom_structure['keys'][$i]['key_size'] - 8);
|
||||||
|
$keys_atom_offset += $atom_structure['keys'][$i]['key_size']; // key_size includes the 4+4 bytes for key_size and key_namespace
|
||||||
|
|
||||||
|
$info['quicktime']['temp_meta_key_names'][$i] = $atom_structure['keys'][$i]['key_value'];
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1753,56 +1892,56 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($
|
||||||
static $QuicktimeIODSaudioProfileNameLookup = array();
|
static $QuicktimeIODSaudioProfileNameLookup = array();
|
||||||
if (empty($QuicktimeIODSaudioProfileNameLookup)) {
|
if (empty($QuicktimeIODSaudioProfileNameLookup)) {
|
||||||
$QuicktimeIODSaudioProfileNameLookup = array(
|
$QuicktimeIODSaudioProfileNameLookup = array(
|
||||||
0x00 => 'ISO Reserved (0x00)',
|
0x00 => 'ISO Reserved (0x00)',
|
||||||
0x01 => 'Main Audio Profile @ Level 1',
|
0x01 => 'Main Audio Profile @ Level 1',
|
||||||
0x02 => 'Main Audio Profile @ Level 2',
|
0x02 => 'Main Audio Profile @ Level 2',
|
||||||
0x03 => 'Main Audio Profile @ Level 3',
|
0x03 => 'Main Audio Profile @ Level 3',
|
||||||
0x04 => 'Main Audio Profile @ Level 4',
|
0x04 => 'Main Audio Profile @ Level 4',
|
||||||
0x05 => 'Scalable Audio Profile @ Level 1',
|
0x05 => 'Scalable Audio Profile @ Level 1',
|
||||||
0x06 => 'Scalable Audio Profile @ Level 2',
|
0x06 => 'Scalable Audio Profile @ Level 2',
|
||||||
0x07 => 'Scalable Audio Profile @ Level 3',
|
0x07 => 'Scalable Audio Profile @ Level 3',
|
||||||
0x08 => 'Scalable Audio Profile @ Level 4',
|
0x08 => 'Scalable Audio Profile @ Level 4',
|
||||||
0x09 => 'Speech Audio Profile @ Level 1',
|
0x09 => 'Speech Audio Profile @ Level 1',
|
||||||
0x0A => 'Speech Audio Profile @ Level 2',
|
0x0A => 'Speech Audio Profile @ Level 2',
|
||||||
0x0B => 'Synthetic Audio Profile @ Level 1',
|
0x0B => 'Synthetic Audio Profile @ Level 1',
|
||||||
0x0C => 'Synthetic Audio Profile @ Level 2',
|
0x0C => 'Synthetic Audio Profile @ Level 2',
|
||||||
0x0D => 'Synthetic Audio Profile @ Level 3',
|
0x0D => 'Synthetic Audio Profile @ Level 3',
|
||||||
0x0E => 'High Quality Audio Profile @ Level 1',
|
0x0E => 'High Quality Audio Profile @ Level 1',
|
||||||
0x0F => 'High Quality Audio Profile @ Level 2',
|
0x0F => 'High Quality Audio Profile @ Level 2',
|
||||||
0x10 => 'High Quality Audio Profile @ Level 3',
|
0x10 => 'High Quality Audio Profile @ Level 3',
|
||||||
0x11 => 'High Quality Audio Profile @ Level 4',
|
0x11 => 'High Quality Audio Profile @ Level 4',
|
||||||
0x12 => 'High Quality Audio Profile @ Level 5',
|
0x12 => 'High Quality Audio Profile @ Level 5',
|
||||||
0x13 => 'High Quality Audio Profile @ Level 6',
|
0x13 => 'High Quality Audio Profile @ Level 6',
|
||||||
0x14 => 'High Quality Audio Profile @ Level 7',
|
0x14 => 'High Quality Audio Profile @ Level 7',
|
||||||
0x15 => 'High Quality Audio Profile @ Level 8',
|
0x15 => 'High Quality Audio Profile @ Level 8',
|
||||||
0x16 => 'Low Delay Audio Profile @ Level 1',
|
0x16 => 'Low Delay Audio Profile @ Level 1',
|
||||||
0x17 => 'Low Delay Audio Profile @ Level 2',
|
0x17 => 'Low Delay Audio Profile @ Level 2',
|
||||||
0x18 => 'Low Delay Audio Profile @ Level 3',
|
0x18 => 'Low Delay Audio Profile @ Level 3',
|
||||||
0x19 => 'Low Delay Audio Profile @ Level 4',
|
0x19 => 'Low Delay Audio Profile @ Level 4',
|
||||||
0x1A => 'Low Delay Audio Profile @ Level 5',
|
0x1A => 'Low Delay Audio Profile @ Level 5',
|
||||||
0x1B => 'Low Delay Audio Profile @ Level 6',
|
0x1B => 'Low Delay Audio Profile @ Level 6',
|
||||||
0x1C => 'Low Delay Audio Profile @ Level 7',
|
0x1C => 'Low Delay Audio Profile @ Level 7',
|
||||||
0x1D => 'Low Delay Audio Profile @ Level 8',
|
0x1D => 'Low Delay Audio Profile @ Level 8',
|
||||||
0x1E => 'Natural Audio Profile @ Level 1',
|
0x1E => 'Natural Audio Profile @ Level 1',
|
||||||
0x1F => 'Natural Audio Profile @ Level 2',
|
0x1F => 'Natural Audio Profile @ Level 2',
|
||||||
0x20 => 'Natural Audio Profile @ Level 3',
|
0x20 => 'Natural Audio Profile @ Level 3',
|
||||||
0x21 => 'Natural Audio Profile @ Level 4',
|
0x21 => 'Natural Audio Profile @ Level 4',
|
||||||
0x22 => 'Mobile Audio Internetworking Profile @ Level 1',
|
0x22 => 'Mobile Audio Internetworking Profile @ Level 1',
|
||||||
0x23 => 'Mobile Audio Internetworking Profile @ Level 2',
|
0x23 => 'Mobile Audio Internetworking Profile @ Level 2',
|
||||||
0x24 => 'Mobile Audio Internetworking Profile @ Level 3',
|
0x24 => 'Mobile Audio Internetworking Profile @ Level 3',
|
||||||
0x25 => 'Mobile Audio Internetworking Profile @ Level 4',
|
0x25 => 'Mobile Audio Internetworking Profile @ Level 4',
|
||||||
0x26 => 'Mobile Audio Internetworking Profile @ Level 5',
|
0x26 => 'Mobile Audio Internetworking Profile @ Level 5',
|
||||||
0x27 => 'Mobile Audio Internetworking Profile @ Level 6',
|
0x27 => 'Mobile Audio Internetworking Profile @ Level 6',
|
||||||
0x28 => 'AAC Profile @ Level 1',
|
0x28 => 'AAC Profile @ Level 1',
|
||||||
0x29 => 'AAC Profile @ Level 2',
|
0x29 => 'AAC Profile @ Level 2',
|
||||||
0x2A => 'AAC Profile @ Level 4',
|
0x2A => 'AAC Profile @ Level 4',
|
||||||
0x2B => 'AAC Profile @ Level 5',
|
0x2B => 'AAC Profile @ Level 5',
|
||||||
0x2C => 'High Efficiency AAC Profile @ Level 2',
|
0x2C => 'High Efficiency AAC Profile @ Level 2',
|
||||||
0x2D => 'High Efficiency AAC Profile @ Level 3',
|
0x2D => 'High Efficiency AAC Profile @ Level 3',
|
||||||
0x2E => 'High Efficiency AAC Profile @ Level 4',
|
0x2E => 'High Efficiency AAC Profile @ Level 4',
|
||||||
0x2F => 'High Efficiency AAC Profile @ Level 5',
|
0x2F => 'High Efficiency AAC Profile @ Level 5',
|
||||||
0xFE => 'Not part of MPEG-4 audio profiles',
|
0xFE => 'Not part of MPEG-4 audio profiles',
|
||||||
0xFF => 'No audio capability required',
|
0xFF => 'No audio capability required',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (isset($QuicktimeIODSaudioProfileNameLookup[$audio_profile_id]) ? $QuicktimeIODSaudioProfileNameLookup[$audio_profile_id] : 'ISO Reserved / User Private');
|
return (isset($QuicktimeIODSaudioProfileNameLookup[$audio_profile_id]) ? $QuicktimeIODSaudioProfileNameLookup[$audio_profile_id] : 'ISO Reserved / User Private');
|
||||||
|
@ -2111,8 +2250,18 @@ echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br
|
||||||
public function CopyToAppropriateCommentsSection($keyname, $data, $boxname='') {
|
public function CopyToAppropriateCommentsSection($keyname, $data, $boxname='') {
|
||||||
static $handyatomtranslatorarray = array();
|
static $handyatomtranslatorarray = array();
|
||||||
if (empty($handyatomtranslatorarray)) {
|
if (empty($handyatomtranslatorarray)) {
|
||||||
|
// http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
|
||||||
|
// http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt
|
||||||
|
// http://atomicparsley.sourceforge.net/mpeg-4files.html
|
||||||
|
// https://code.google.com/p/mp4v2/wiki/iTunesMetadata
|
||||||
|
$handyatomtranslatorarray["\xA9".'alb'] = 'album'; // iTunes 4.0
|
||||||
|
$handyatomtranslatorarray["\xA9".'ART'] = 'artist';
|
||||||
|
$handyatomtranslatorarray["\xA9".'art'] = 'artist'; // iTunes 4.0
|
||||||
|
$handyatomtranslatorarray["\xA9".'aut'] = 'author';
|
||||||
|
$handyatomtranslatorarray["\xA9".'cmt'] = 'comment'; // iTunes 4.0
|
||||||
|
$handyatomtranslatorarray["\xA9".'com'] = 'comment';
|
||||||
$handyatomtranslatorarray["\xA9".'cpy'] = 'copyright';
|
$handyatomtranslatorarray["\xA9".'cpy'] = 'copyright';
|
||||||
$handyatomtranslatorarray["\xA9".'day'] = 'creation_date'; // iTunes 4.0
|
$handyatomtranslatorarray["\xA9".'day'] = 'creation_date'; // iTunes 4.0
|
||||||
$handyatomtranslatorarray["\xA9".'dir'] = 'director';
|
$handyatomtranslatorarray["\xA9".'dir'] = 'director';
|
||||||
$handyatomtranslatorarray["\xA9".'ed1'] = 'edit1';
|
$handyatomtranslatorarray["\xA9".'ed1'] = 'edit1';
|
||||||
$handyatomtranslatorarray["\xA9".'ed2'] = 'edit2';
|
$handyatomtranslatorarray["\xA9".'ed2'] = 'edit2';
|
||||||
|
@ -2123,64 +2272,60 @@ echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br
|
||||||
$handyatomtranslatorarray["\xA9".'ed7'] = 'edit7';
|
$handyatomtranslatorarray["\xA9".'ed7'] = 'edit7';
|
||||||
$handyatomtranslatorarray["\xA9".'ed8'] = 'edit8';
|
$handyatomtranslatorarray["\xA9".'ed8'] = 'edit8';
|
||||||
$handyatomtranslatorarray["\xA9".'ed9'] = 'edit9';
|
$handyatomtranslatorarray["\xA9".'ed9'] = 'edit9';
|
||||||
|
$handyatomtranslatorarray["\xA9".'enc'] = 'encoded_by';
|
||||||
$handyatomtranslatorarray["\xA9".'fmt'] = 'format';
|
$handyatomtranslatorarray["\xA9".'fmt'] = 'format';
|
||||||
|
$handyatomtranslatorarray["\xA9".'gen'] = 'genre'; // iTunes 4.0
|
||||||
|
$handyatomtranslatorarray["\xA9".'grp'] = 'grouping'; // iTunes 4.2
|
||||||
|
$handyatomtranslatorarray["\xA9".'hst'] = 'host_computer';
|
||||||
$handyatomtranslatorarray["\xA9".'inf'] = 'information';
|
$handyatomtranslatorarray["\xA9".'inf'] = 'information';
|
||||||
|
$handyatomtranslatorarray["\xA9".'lyr'] = 'lyrics'; // iTunes 5.0
|
||||||
|
$handyatomtranslatorarray["\xA9".'mak'] = 'make';
|
||||||
|
$handyatomtranslatorarray["\xA9".'mod'] = 'model';
|
||||||
|
$handyatomtranslatorarray["\xA9".'nam'] = 'title'; // iTunes 4.0
|
||||||
|
$handyatomtranslatorarray["\xA9".'ope'] = 'composer';
|
||||||
$handyatomtranslatorarray["\xA9".'prd'] = 'producer';
|
$handyatomtranslatorarray["\xA9".'prd'] = 'producer';
|
||||||
|
$handyatomtranslatorarray["\xA9".'PRD'] = 'product';
|
||||||
$handyatomtranslatorarray["\xA9".'prf'] = 'performers';
|
$handyatomtranslatorarray["\xA9".'prf'] = 'performers';
|
||||||
$handyatomtranslatorarray["\xA9".'req'] = 'system_requirements';
|
$handyatomtranslatorarray["\xA9".'req'] = 'system_requirements';
|
||||||
$handyatomtranslatorarray["\xA9".'src'] = 'source_credit';
|
$handyatomtranslatorarray["\xA9".'src'] = 'source_credit';
|
||||||
$handyatomtranslatorarray["\xA9".'wrt'] = 'writer';
|
|
||||||
|
|
||||||
// http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
|
|
||||||
$handyatomtranslatorarray["\xA9".'nam'] = 'title'; // iTunes 4.0
|
|
||||||
$handyatomtranslatorarray["\xA9".'cmt'] = 'comment'; // iTunes 4.0
|
|
||||||
$handyatomtranslatorarray["\xA9".'wrn'] = 'warning';
|
|
||||||
$handyatomtranslatorarray["\xA9".'hst'] = 'host_computer';
|
|
||||||
$handyatomtranslatorarray["\xA9".'mak'] = 'make';
|
|
||||||
$handyatomtranslatorarray["\xA9".'mod'] = 'model';
|
|
||||||
$handyatomtranslatorarray["\xA9".'PRD'] = 'product';
|
|
||||||
$handyatomtranslatorarray["\xA9".'swr'] = 'software';
|
$handyatomtranslatorarray["\xA9".'swr'] = 'software';
|
||||||
$handyatomtranslatorarray["\xA9".'aut'] = 'author';
|
$handyatomtranslatorarray["\xA9".'too'] = 'encoding_tool'; // iTunes 4.0
|
||||||
$handyatomtranslatorarray["\xA9".'ART'] = 'artist';
|
|
||||||
$handyatomtranslatorarray["\xA9".'trk'] = 'track';
|
$handyatomtranslatorarray["\xA9".'trk'] = 'track';
|
||||||
$handyatomtranslatorarray["\xA9".'alb'] = 'album'; // iTunes 4.0
|
|
||||||
$handyatomtranslatorarray["\xA9".'com'] = 'comment';
|
|
||||||
$handyatomtranslatorarray["\xA9".'gen'] = 'genre'; // iTunes 4.0
|
|
||||||
$handyatomtranslatorarray["\xA9".'ope'] = 'composer';
|
|
||||||
$handyatomtranslatorarray["\xA9".'url'] = 'url';
|
$handyatomtranslatorarray["\xA9".'url'] = 'url';
|
||||||
$handyatomtranslatorarray["\xA9".'enc'] = 'encoder';
|
$handyatomtranslatorarray["\xA9".'wrn'] = 'warning';
|
||||||
|
$handyatomtranslatorarray["\xA9".'wrt'] = 'composer';
|
||||||
// http://atomicparsley.sourceforge.net/mpeg-4files.html
|
|
||||||
$handyatomtranslatorarray["\xA9".'art'] = 'artist'; // iTunes 4.0
|
|
||||||
$handyatomtranslatorarray['aART'] = 'album_artist';
|
$handyatomtranslatorarray['aART'] = 'album_artist';
|
||||||
$handyatomtranslatorarray['trkn'] = 'track_number'; // iTunes 4.0
|
$handyatomtranslatorarray['apID'] = 'purchase_account';
|
||||||
$handyatomtranslatorarray['disk'] = 'disc_number'; // iTunes 4.0
|
$handyatomtranslatorarray['catg'] = 'category'; // iTunes 4.9
|
||||||
$handyatomtranslatorarray['gnre'] = 'genre'; // iTunes 4.0
|
$handyatomtranslatorarray['covr'] = 'picture'; // iTunes 4.0
|
||||||
$handyatomtranslatorarray["\xA9".'too'] = 'encoder'; // iTunes 4.0
|
$handyatomtranslatorarray['cpil'] = 'compilation'; // iTunes 4.0
|
||||||
$handyatomtranslatorarray['tmpo'] = 'bpm'; // iTunes 4.0
|
$handyatomtranslatorarray['cprt'] = 'copyright'; // iTunes 4.0?
|
||||||
$handyatomtranslatorarray['cprt'] = 'copyright'; // iTunes 4.0?
|
$handyatomtranslatorarray['desc'] = 'description'; // iTunes 5.0
|
||||||
$handyatomtranslatorarray['cpil'] = 'compilation'; // iTunes 4.0
|
$handyatomtranslatorarray['disk'] = 'disc_number'; // iTunes 4.0
|
||||||
$handyatomtranslatorarray['covr'] = 'picture'; // iTunes 4.0
|
$handyatomtranslatorarray['egid'] = 'episode_guid'; // iTunes 4.9
|
||||||
$handyatomtranslatorarray['rtng'] = 'rating'; // iTunes 4.0
|
$handyatomtranslatorarray['gnre'] = 'genre'; // iTunes 4.0
|
||||||
$handyatomtranslatorarray["\xA9".'grp'] = 'grouping'; // iTunes 4.2
|
$handyatomtranslatorarray['hdvd'] = 'hd_video'; // iTunes 4.0
|
||||||
$handyatomtranslatorarray['stik'] = 'stik'; // iTunes 4.9
|
$handyatomtranslatorarray['ldes'] = 'description_long'; //
|
||||||
$handyatomtranslatorarray['pcst'] = 'podcast'; // iTunes 4.9
|
$handyatomtranslatorarray['keyw'] = 'keyword'; // iTunes 4.9
|
||||||
$handyatomtranslatorarray['catg'] = 'category'; // iTunes 4.9
|
$handyatomtranslatorarray['pcst'] = 'podcast'; // iTunes 4.9
|
||||||
$handyatomtranslatorarray['keyw'] = 'keyword'; // iTunes 4.9
|
$handyatomtranslatorarray['pgap'] = 'gapless_playback'; // iTunes 7.0
|
||||||
$handyatomtranslatorarray['purl'] = 'podcast_url'; // iTunes 4.9
|
$handyatomtranslatorarray['purd'] = 'purchase_date'; // iTunes 6.0.2
|
||||||
$handyatomtranslatorarray['egid'] = 'episode_guid'; // iTunes 4.9
|
$handyatomtranslatorarray['purl'] = 'podcast_url'; // iTunes 4.9
|
||||||
$handyatomtranslatorarray['desc'] = 'description'; // iTunes 5.0
|
$handyatomtranslatorarray['rtng'] = 'rating'; // iTunes 4.0
|
||||||
$handyatomtranslatorarray["\xA9".'lyr'] = 'lyrics'; // iTunes 5.0
|
$handyatomtranslatorarray['soaa'] = 'sort_album_artist'; //
|
||||||
$handyatomtranslatorarray['tvnn'] = 'tv_network_name'; // iTunes 6.0
|
$handyatomtranslatorarray['soal'] = 'sort_album'; //
|
||||||
$handyatomtranslatorarray['tvsh'] = 'tv_show_name'; // iTunes 6.0
|
$handyatomtranslatorarray['soar'] = 'sort_artist'; //
|
||||||
$handyatomtranslatorarray['tvsn'] = 'tv_season'; // iTunes 6.0
|
$handyatomtranslatorarray['soco'] = 'sort_composer'; //
|
||||||
$handyatomtranslatorarray['tves'] = 'tv_episode'; // iTunes 6.0
|
$handyatomtranslatorarray['sonm'] = 'sort_title'; //
|
||||||
$handyatomtranslatorarray['purd'] = 'purchase_date'; // iTunes 6.0.2
|
$handyatomtranslatorarray['sosn'] = 'sort_show'; //
|
||||||
$handyatomtranslatorarray['pgap'] = 'gapless_playback'; // iTunes 7.0
|
$handyatomtranslatorarray['stik'] = 'stik'; // iTunes 4.9
|
||||||
|
$handyatomtranslatorarray['tmpo'] = 'bpm'; // iTunes 4.0
|
||||||
// http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt
|
$handyatomtranslatorarray['trkn'] = 'track_number'; // iTunes 4.0
|
||||||
|
$handyatomtranslatorarray['tven'] = 'tv_episode_id'; //
|
||||||
|
$handyatomtranslatorarray['tves'] = 'tv_episode'; // iTunes 6.0
|
||||||
|
$handyatomtranslatorarray['tvnn'] = 'tv_network_name'; // iTunes 6.0
|
||||||
|
$handyatomtranslatorarray['tvsh'] = 'tv_show_name'; // iTunes 6.0
|
||||||
|
$handyatomtranslatorarray['tvsn'] = 'tv_season'; // iTunes 6.0
|
||||||
|
|
||||||
// boxnames:
|
// boxnames:
|
||||||
/*
|
/*
|
||||||
|
@ -2225,7 +2370,14 @@ echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br
|
||||||
$data = array('data'=>$data, 'image_mime'=>$image_mime);
|
$data = array('data'=>$data, 'image_mime'=>$image_mime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$info['quicktime']['comments'][$comment_key][] = $data;
|
$gooddata = array($data);
|
||||||
|
if ($comment_key == 'genre') {
|
||||||
|
// some other taggers separate multiple genres with semicolon, e.g. "Heavy Metal;Thrash Metal;Metal"
|
||||||
|
$gooddata = explode(';', $data);
|
||||||
|
}
|
||||||
|
foreach ($gooddata as $data) {
|
||||||
|
$info['quicktime']['comments'][$comment_key][] = $data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2243,4 +2395,79 @@ echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br
|
||||||
return substr($pascalstring, 1);
|
return substr($pascalstring, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
// helper functions for m4b audiobook chapters
|
||||||
|
// code by Steffen Hartmann 2015-Nov-08
|
||||||
|
*/
|
||||||
|
public function search_tag_by_key($info, $tag, $history, &$result) {
|
||||||
|
foreach ($info as $key => $value) {
|
||||||
|
$key_history = $history.'/'.$key;
|
||||||
|
if ($key === $tag) {
|
||||||
|
$result[] = array($key_history, $info);
|
||||||
|
} else {
|
||||||
|
if (is_array($value)) {
|
||||||
|
$this->search_tag_by_key($value, $tag, $key_history, $result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function search_tag_by_pair($info, $k, $v, $history, &$result) {
|
||||||
|
foreach ($info as $key => $value) {
|
||||||
|
$key_history = $history.'/'.$key;
|
||||||
|
if (($key === $k) && ($value === $v)) {
|
||||||
|
$result[] = array($key_history, $info);
|
||||||
|
} else {
|
||||||
|
if (is_array($value)) {
|
||||||
|
$this->search_tag_by_pair($value, $k, $v, $key_history, $result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function quicktime_time_to_sample_table($info) {
|
||||||
|
$res = array();
|
||||||
|
$this->search_tag_by_pair($info['quicktime']['moov'], 'name', 'stbl', 'quicktime/moov', $res);
|
||||||
|
foreach ($res as $value) {
|
||||||
|
$stbl_res = array();
|
||||||
|
$this->search_tag_by_pair($value[1], 'data_format', 'text', $value[0], $stbl_res);
|
||||||
|
if (count($stbl_res) > 0) {
|
||||||
|
$stts_res = array();
|
||||||
|
$this->search_tag_by_key($value[1], 'time_to_sample_table', $value[0], $stts_res);
|
||||||
|
if (count($stts_res) > 0) {
|
||||||
|
return $stts_res[0][1]['time_to_sample_table'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
function quicktime_bookmark_time_scale($info) {
|
||||||
|
$time_scale = '';
|
||||||
|
$ts_prefix_len = 0;
|
||||||
|
$res = array();
|
||||||
|
$this->search_tag_by_pair($info['quicktime']['moov'], 'name', 'stbl', 'quicktime/moov', $res);
|
||||||
|
foreach ($res as $value) {
|
||||||
|
$stbl_res = array();
|
||||||
|
$this->search_tag_by_pair($value[1], 'data_format', 'text', $value[0], $stbl_res);
|
||||||
|
if (count($stbl_res) > 0) {
|
||||||
|
$ts_res = array();
|
||||||
|
$this->search_tag_by_key($info['quicktime']['moov'], 'time_scale', 'quicktime/moov', $ts_res);
|
||||||
|
foreach ($ts_res as $value) {
|
||||||
|
$prefix = substr($value[0], 0, -12);
|
||||||
|
if ((substr($stbl_res[0][0], 0, strlen($prefix)) === $prefix) && ($ts_prefix_len < strlen($prefix))) {
|
||||||
|
$time_scale = $value[1]['time_scale'];
|
||||||
|
$ts_prefix_len = strlen($prefix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $time_scale;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
// END helper functions for m4b audiobook chapters
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
0
app/Library/getid3/getid3/module.audio-video.real.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio-video.real.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio-video.riff.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio-video.riff.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio-video.swf.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio-video.swf.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio-video.ts.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio-video.ts.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.aa.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.aa.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.aac.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.aac.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.ac3.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.ac3.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.amr.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.amr.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.au.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.au.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.avr.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.avr.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.bonk.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.bonk.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.dss.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.dss.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.dts.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.dts.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.flac.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.flac.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.la.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.la.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.lpac.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.lpac.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.midi.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.midi.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.mod.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.mod.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.monkey.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.monkey.php
Executable file → Normal file
18
app/Library/getid3/getid3/module.audio.mp3.php
Executable file → Normal file
18
app/Library/getid3/getid3/module.audio.mp3.php
Executable file → Normal file
|
@ -437,7 +437,6 @@ class getid3_mp3 extends getid3_handler
|
||||||
// and $cc... is the audio data
|
// and $cc... is the audio data
|
||||||
|
|
||||||
$head4 = substr($headerstring, 0, 4);
|
$head4 = substr($headerstring, 0, 4);
|
||||||
|
|
||||||
static $MPEGaudioHeaderDecodeCache = array();
|
static $MPEGaudioHeaderDecodeCache = array();
|
||||||
if (isset($MPEGaudioHeaderDecodeCache[$head4])) {
|
if (isset($MPEGaudioHeaderDecodeCache[$head4])) {
|
||||||
$MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$head4];
|
$MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$head4];
|
||||||
|
@ -648,9 +647,20 @@ class getid3_mp3 extends getid3_handler
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (($thisfile_mpeg_audio['bitrate'] == 'free') && !empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
|
//if (($thisfile_mpeg_audio['bitrate'] == 'free') && !empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
|
||||||
if (!empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
|
//if (!empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
|
||||||
|
if (!empty($thisfile_mpeg_audio['VBR_frames'])) {
|
||||||
|
$used_filesize = 0;
|
||||||
|
if (!empty($thisfile_mpeg_audio['VBR_bytes'])) {
|
||||||
|
$used_filesize = $thisfile_mpeg_audio['VBR_bytes'];
|
||||||
|
} elseif (!empty($info['filesize'])) {
|
||||||
|
$used_filesize = $info['filesize'];
|
||||||
|
$used_filesize -= intval(@$info['id3v2']['headerlength']);
|
||||||
|
$used_filesize -= (isset($info['id3v1']) ? 128 : 0);
|
||||||
|
$used_filesize -= (isset($info['tag_offset_end']) ? $info['tag_offset_end'] - $info['tag_offset_start'] : 0);
|
||||||
|
$info['warning'][] = 'MP3.Xing header missing VBR_bytes, assuming MPEG audio portion of file is '.number_format($used_filesize).' bytes';
|
||||||
|
}
|
||||||
|
|
||||||
$framelengthfloat = $thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames'];
|
$framelengthfloat = $used_filesize / $thisfile_mpeg_audio['VBR_frames'];
|
||||||
|
|
||||||
if ($thisfile_mpeg_audio['layer'] == '1') {
|
if ($thisfile_mpeg_audio['layer'] == '1') {
|
||||||
// BitRate = (((FrameLengthInBytes / 4) - Padding) * SampleRate) / 12
|
// BitRate = (((FrameLengthInBytes / 4) - Padding) * SampleRate) / 12
|
||||||
|
@ -948,7 +958,7 @@ class getid3_mp3 extends getid3_handler
|
||||||
}
|
}
|
||||||
$thisfile_mpeg_audio['VBR_bitrate'] = (isset($thisfile_mpeg_audio['VBR_bytes']) ? (($thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames']) * 8) * ($info['audio']['sample_rate'] / $bytes_per_frame) : 0);
|
$thisfile_mpeg_audio['VBR_bitrate'] = (isset($thisfile_mpeg_audio['VBR_bytes']) ? (($thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames']) * 8) * ($info['audio']['sample_rate'] / $bytes_per_frame) : 0);
|
||||||
if ($thisfile_mpeg_audio['VBR_bitrate'] > 0) {
|
if ($thisfile_mpeg_audio['VBR_bitrate'] > 0) {
|
||||||
$info['audio']['bitrate'] = $thisfile_mpeg_audio['VBR_bitrate'];
|
$info['audio']['bitrate'] = $thisfile_mpeg_audio['VBR_bitrate'];
|
||||||
$thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio['VBR_bitrate']; // to avoid confusion
|
$thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio['VBR_bitrate']; // to avoid confusion
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
0
app/Library/getid3/getid3/module.audio.mpc.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.mpc.php
Executable file → Normal file
1
app/Library/getid3/getid3/module.audio.ogg.php
Executable file → Normal file
1
app/Library/getid3/getid3/module.audio.ogg.php
Executable file → Normal file
|
@ -562,6 +562,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$VendorSize = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4));
|
$VendorSize = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4));
|
||||||
|
|
0
app/Library/getid3/getid3/module.audio.optimfrog.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.optimfrog.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.rkau.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.rkau.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.shorten.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.shorten.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.tta.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.tta.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.voc.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.voc.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.vqf.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.vqf.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.wavpack.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.audio.wavpack.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.graphic.bmp.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.graphic.bmp.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.graphic.efax.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.graphic.efax.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.graphic.gif.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.graphic.gif.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.graphic.jpg.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.graphic.jpg.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.graphic.pcd.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.graphic.pcd.php
Executable file → Normal file
32
app/Library/getid3/getid3/module.graphic.png.php
Executable file → Normal file
32
app/Library/getid3/getid3/module.graphic.png.php
Executable file → Normal file
|
@ -17,8 +17,10 @@
|
||||||
|
|
||||||
class getid3_png extends getid3_handler
|
class getid3_png extends getid3_handler
|
||||||
{
|
{
|
||||||
|
public $max_data_bytes = 10000000; // if data chunk is larger than this do not read it completely (getID3 only needs the first few dozen bytes for parsing)
|
||||||
|
|
||||||
public function Analyze() {
|
public function Analyze() {
|
||||||
|
|
||||||
$info = &$this->getid3->info;
|
$info = &$this->getid3->info;
|
||||||
|
|
||||||
// shortcut
|
// shortcut
|
||||||
|
@ -44,14 +46,24 @@ class getid3_png extends getid3_handler
|
||||||
|
|
||||||
while ((($this->ftell() - (strlen($PNGfiledata) - $offset)) < $info['filesize'])) {
|
while ((($this->ftell() - (strlen($PNGfiledata) - $offset)) < $info['filesize'])) {
|
||||||
$chunk['data_length'] = getid3_lib::BigEndian2Int(substr($PNGfiledata, $offset, 4));
|
$chunk['data_length'] = getid3_lib::BigEndian2Int(substr($PNGfiledata, $offset, 4));
|
||||||
$offset += 4;
|
if ($chunk['data_length'] === false) {
|
||||||
while (((strlen($PNGfiledata) - $offset) < ($chunk['data_length'] + 4)) && ($this->ftell() < $info['filesize'])) {
|
$info['error'][] = 'Failed to read data_length at offset '.$offset;
|
||||||
$PNGfiledata .= $this->fread($this->getid3->fread_buffer_size());
|
return false;
|
||||||
}
|
}
|
||||||
$chunk['type_text'] = substr($PNGfiledata, $offset, 4);
|
$offset += 4;
|
||||||
|
$truncated_data = false;
|
||||||
|
while (((strlen($PNGfiledata) - $offset) < ($chunk['data_length'] + 4)) && ($this->ftell() < $info['filesize'])) {
|
||||||
|
if (strlen($PNGfiledata) < $this->max_data_bytes) {
|
||||||
|
$PNGfiledata .= $this->fread($this->getid3->fread_buffer_size());
|
||||||
|
} else {
|
||||||
|
$info['warning'][] = 'At offset '.$offset.' chunk "'.substr($PNGfiledata, $offset, 4).'" exceeded max_data_bytes value of '.$this->max_data_bytes.', data chunk will be truncated at '.(strlen($PNGfiledata) - 8).' bytes';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$chunk['type_text'] = substr($PNGfiledata, $offset, 4);
|
||||||
$offset += 4;
|
$offset += 4;
|
||||||
$chunk['type_raw'] = getid3_lib::BigEndian2Int($chunk['type_text']);
|
$chunk['type_raw'] = getid3_lib::BigEndian2Int($chunk['type_text']);
|
||||||
$chunk['data'] = substr($PNGfiledata, $offset, $chunk['data_length']);
|
$chunk['data'] = substr($PNGfiledata, $offset, $chunk['data_length']);
|
||||||
$offset += $chunk['data_length'];
|
$offset += $chunk['data_length'];
|
||||||
$chunk['crc'] = getid3_lib::BigEndian2Int(substr($PNGfiledata, $offset, 4));
|
$chunk['crc'] = getid3_lib::BigEndian2Int(substr($PNGfiledata, $offset, 4));
|
||||||
$offset += 4;
|
$offset += 4;
|
||||||
|
@ -162,7 +174,7 @@ class getid3_png extends getid3_handler
|
||||||
|
|
||||||
case 'iCCP': // Embedded ICC Profile
|
case 'iCCP': // Embedded ICC Profile
|
||||||
$thisfile_png_chunk_type_text['header'] = $chunk;
|
$thisfile_png_chunk_type_text['header'] = $chunk;
|
||||||
list($profilename, $compressiondata) = explode("\x00", $chunk['data'], 2);
|
list($profilename, $compressiondata) = explode("\x00", $chunk['data'], 2);
|
||||||
$thisfile_png_chunk_type_text['profile_name'] = $profilename;
|
$thisfile_png_chunk_type_text['profile_name'] = $profilename;
|
||||||
$thisfile_png_chunk_type_text['compression_method'] = getid3_lib::BigEndian2Int(substr($compressiondata, 0, 1));
|
$thisfile_png_chunk_type_text['compression_method'] = getid3_lib::BigEndian2Int(substr($compressiondata, 0, 1));
|
||||||
$thisfile_png_chunk_type_text['compression_profile'] = substr($compressiondata, 1);
|
$thisfile_png_chunk_type_text['compression_profile'] = substr($compressiondata, 1);
|
||||||
|
@ -173,7 +185,7 @@ class getid3_png extends getid3_handler
|
||||||
|
|
||||||
case 'tEXt': // Textual Data
|
case 'tEXt': // Textual Data
|
||||||
$thisfile_png_chunk_type_text['header'] = $chunk;
|
$thisfile_png_chunk_type_text['header'] = $chunk;
|
||||||
list($keyword, $text) = explode("\x00", $chunk['data'], 2);
|
list($keyword, $text) = explode("\x00", $chunk['data'], 2);
|
||||||
$thisfile_png_chunk_type_text['keyword'] = $keyword;
|
$thisfile_png_chunk_type_text['keyword'] = $keyword;
|
||||||
$thisfile_png_chunk_type_text['text'] = $text;
|
$thisfile_png_chunk_type_text['text'] = $text;
|
||||||
|
|
||||||
|
@ -183,7 +195,7 @@ class getid3_png extends getid3_handler
|
||||||
|
|
||||||
case 'zTXt': // Compressed Textual Data
|
case 'zTXt': // Compressed Textual Data
|
||||||
$thisfile_png_chunk_type_text['header'] = $chunk;
|
$thisfile_png_chunk_type_text['header'] = $chunk;
|
||||||
list($keyword, $otherdata) = explode("\x00", $chunk['data'], 2);
|
list($keyword, $otherdata) = explode("\x00", $chunk['data'], 2);
|
||||||
$thisfile_png_chunk_type_text['keyword'] = $keyword;
|
$thisfile_png_chunk_type_text['keyword'] = $keyword;
|
||||||
$thisfile_png_chunk_type_text['compression_method'] = getid3_lib::BigEndian2Int(substr($otherdata, 0, 1));
|
$thisfile_png_chunk_type_text['compression_method'] = getid3_lib::BigEndian2Int(substr($otherdata, 0, 1));
|
||||||
$thisfile_png_chunk_type_text['compressed_text'] = substr($otherdata, 1);
|
$thisfile_png_chunk_type_text['compressed_text'] = substr($otherdata, 1);
|
||||||
|
@ -206,7 +218,7 @@ class getid3_png extends getid3_handler
|
||||||
|
|
||||||
case 'iTXt': // International Textual Data
|
case 'iTXt': // International Textual Data
|
||||||
$thisfile_png_chunk_type_text['header'] = $chunk;
|
$thisfile_png_chunk_type_text['header'] = $chunk;
|
||||||
list($keyword, $otherdata) = explode("\x00", $chunk['data'], 2);
|
list($keyword, $otherdata) = explode("\x00", $chunk['data'], 2);
|
||||||
$thisfile_png_chunk_type_text['keyword'] = $keyword;
|
$thisfile_png_chunk_type_text['keyword'] = $keyword;
|
||||||
$thisfile_png_chunk_type_text['compression'] = (bool) getid3_lib::BigEndian2Int(substr($otherdata, 0, 1));
|
$thisfile_png_chunk_type_text['compression'] = (bool) getid3_lib::BigEndian2Int(substr($otherdata, 0, 1));
|
||||||
$thisfile_png_chunk_type_text['compression_method'] = getid3_lib::BigEndian2Int(substr($otherdata, 1, 1));
|
$thisfile_png_chunk_type_text['compression_method'] = getid3_lib::BigEndian2Int(substr($otherdata, 1, 1));
|
||||||
|
@ -307,7 +319,7 @@ class getid3_png extends getid3_handler
|
||||||
|
|
||||||
case 'sPLT': // Suggested Palette
|
case 'sPLT': // Suggested Palette
|
||||||
$thisfile_png_chunk_type_text['header'] = $chunk;
|
$thisfile_png_chunk_type_text['header'] = $chunk;
|
||||||
list($palettename, $otherdata) = explode("\x00", $chunk['data'], 2);
|
list($palettename, $otherdata) = explode("\x00", $chunk['data'], 2);
|
||||||
$thisfile_png_chunk_type_text['palette_name'] = $palettename;
|
$thisfile_png_chunk_type_text['palette_name'] = $palettename;
|
||||||
$sPLToffset = 0;
|
$sPLToffset = 0;
|
||||||
$thisfile_png_chunk_type_text['sample_depth_bits'] = getid3_lib::BigEndian2Int(substr($otherdata, $sPLToffset, 1));
|
$thisfile_png_chunk_type_text['sample_depth_bits'] = getid3_lib::BigEndian2Int(substr($otherdata, $sPLToffset, 1));
|
||||||
|
|
0
app/Library/getid3/getid3/module.graphic.svg.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.graphic.svg.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.graphic.tiff.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.graphic.tiff.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.misc.cue.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.misc.cue.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.misc.exe.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.misc.exe.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.misc.iso.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.misc.iso.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.misc.msoffice.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.misc.msoffice.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.misc.par2.php
Executable file → Normal file
0
app/Library/getid3/getid3/module.misc.par2.php
Executable file → Normal file
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue