Beispiel #1
2
function tag_mp3($filename, $songname, $albumname, $artist, $time)
{
    $TaggingFormat = 'UTF-8';
    // Initialize getID3 engine
    $getID3 = new getID3();
    $getID3->setOption(array('encoding' => $TaggingFormat));
    getid3_lib::IncludeDependency('/var/www/html/getid3/getid3/write.php', __FILE__, true);
    // Initialize getID3 tag-writing module
    $tagwriter = new getid3_writetags();
    $tagwriter->filename = $filename;
    $tagwriter->tagformats = array('id3v1', 'id3v2.3');
    // set various options (optional)
    $tagwriter->overwrite_tags = true;
    $tagwriter->tag_encoding = $TaggingFormat;
    $tagwriter->remove_other_tags = true;
    // populate data array
    $TagData['title'][] = $songname;
    $TagData['artist'][] = $artist;
    $TagData['album'][] = $albumname;
    $tagwriter->tag_data = $TagData;
    // write tags
    if ($tagwriter->WriteTags()) {
        echo 'Successfully wrote tags<br>';
        if (!empty($tagwriter->warnings)) {
            echo 'There were some warnings:<br>' . implode('<br><br>', $tagwriter->warnings);
        }
    } else {
        echo 'Failed to write tags!<br>' . implode('<br><br>', $tagwriter->errors);
    }
}
Beispiel #2
1
 /**
  * @param $path
  * @param $tags
  *
  * @return bool
  */
 public function write_ID3($path, $tags)
 {
     if (is_file(DOCPATH . $path)) {
         require_once APPPATH . 'libraries/getid3/getid3.php';
         $getID3 = new getID3();
         $getID3->setOption(array('encoding' => 'UTF-8'));
         getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'write.php', __FILE__, TRUE);
         $tagwriter = new getid3_writetags();
         $tagwriter->filename = $path;
         $tagwriter->tag_encoding = 'UTF-8';
         $tagwriter->tagformats = array('id3v1', 'id3v2.3');
         $tagwriter->overwrite_tags = TRUE;
         $tagwriter->tag_data = $tags;
         $tagwriter->WriteTags();
         if (!empty($tagwriter->warnings)) {
             return FALSE;
         }
         return TRUE;
     }
     return FALSE;
 }
Beispiel #3
0
    /**
     * @param object element model
     * @param object element params
     * @param string row data for this element
     */
    function render(&$model, &$params, $file)
    {
        $src = str_replace("\\", "/", COM_FABRIK_LIVESITE . $file);
        ini_set('display_errors', true);
        require_once COM_FABRIK_FRONTEND . DS . 'libs' . DS . 'getid3' . DS . 'getid3' . DS . 'getid3.php';
        require_once COM_FABRIK_FRONTEND . DS . 'libs' . DS . 'getid3' . DS . 'getid3' . DS . 'getid3.lib.php';
        getid3_lib::IncludeDependency(COM_FABRIK_FRONTEND . DS . 'libs' . DS . 'getid3' . DS . 'getid3' . DS . 'extension.cache.mysql.php', __FILE__, true);
        $config = JFactory::getConfig();
        $host = $config->getValue('host');
        $database = $config->getValue('db');
        $username = $config->getValue('user');
        $password = $config->getValue('password');
        $getID3 = new getID3_cached_mysql($host, $database, $username, $password);
        // Analyze file and store returned data in $ThisFileInfo
        $relPath = JPATH_SITE . "{$file}";
        $thisFileInfo = $getID3->analyze($relPath);
        if (array_key_exists('video', $thisFileInfo)) {
            if (array_key_exists('resolution_x', $thisFileInfo['video'])) {
                $w = $thisFileInfo['video']['resolution_x'];
                $h = $thisFileInfo['video']['resolution_y'];
            } else {
                $w = $thisFileInfo['video']['streams']['2']['resolution_x'];
                //for wmv files
                $h = $thisFileInfo['video']['streams']['2']['resolution_y'];
            }
            switch ($thisFileInfo['fileformat']) {
                //add in space for controller
                case 'quicktime':
                    $h += 16;
                    break;
                default:
                    $h += 64;
            }
        }
        $file = str_replace("\\", "/", COM_FABRIK_LIVESITE . $file);
        switch ($thisFileInfo['fileformat']) {
            case 'asf':
                $this->output = '<object id="MediaPlayer" width=' . $w . ' height=' . $h . ' classid="CLSID:22D6f312-B0F6-11D0-94AB-0080C74C7E95" standby="Loading Windows Media Player components�" type="application/x-oleobject" codebase="http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=6,4,7,1112">

<param name="filename" value="http://yourdomain/yourmovie.wmv">
<param name="Showcontrols" value="true">
<param name="autoStart" value="false">

<embed type="application/x-mplayer2" src="' . $src . '" name="MediaPlayer" width=' . $w . ' height=' . $h . '></embed>

</object>
				';
                break;
            default:
                $this->output = "<object width=\"{$w}\" height=\"{$h}\"\n\t\t\tclassid=\"clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B\"\n\t\t\tcodebase=\"http://www.apple.com/qtactivex/qtplugin.cab\">\n\t\t\t<param name=\"src\" value=\"{$src}\">\n\t\t\t<param name=\"autoplay\" value=\"false\">\n\t\t\t<param name=\"controller\" value=\"true\">\n\t\t\t<embed src=\"{$src}\" width=\"{$w}\" height=\"{$h}\"\n\t\t\tautoplay=\"false\" controller=\"true\"\n\t\t\tpluginspage=\"http://www.apple.com/quicktime/download/\">\n\t\t\t</embed>\n\t\t\t\n\t\t\t</object>";
                break;
        }
    }
Beispiel #4
0
 /**
  * Render Video in the form view
  *
  * @param   object  &$model   Element model
  * @param   object  &$params  Element params
  * @param   string  $file     Row data for this element
  *
  * @return  void
  */
 public function render(&$model, &$params, $file)
 {
     $src = str_replace("\\", "/", COM_FABRIK_LIVESITE . $file);
     ini_set('display_errors', true);
     require_once COM_FABRIK_FRONTEND . '/libs/getid3/getid3/getid3.php';
     require_once COM_FABRIK_FRONTEND . '/libs/getid3/getid3/getid3.lib.php';
     getid3_lib::IncludeDependency(COM_FABRIK_FRONTEND . '/libs/getid3/getid3/extension.cache.mysqli.php', __FILE__, true);
     $config = $this->config;
     $host = $config->get('host');
     $database = $config->get('db');
     $username = $config->get('user');
     $password = $config->get('password');
     $getID3 = new getID3_cached_mysqli($host, $database, $username, $password);
     // Analyse file and store returned data in $ThisFileInfo
     $relPath = JPATH_SITE . $file;
     $thisFileInfo = $getID3->analyze($relPath);
     if (array_key_exists('video', $thisFileInfo)) {
         if (array_key_exists('resolution_x', $thisFileInfo['video'])) {
             $w = $thisFileInfo['video']['resolution_x'];
             $h = $thisFileInfo['video']['resolution_y'];
         } else {
             // For wmv files
             $w = $thisFileInfo['video']['streams']['2']['resolution_x'];
             $h = $thisFileInfo['video']['streams']['2']['resolution_y'];
         }
         switch ($thisFileInfo['fileformat']) {
             // Add in space for controller
             case 'quicktime':
                 $h += 16;
                 break;
             default:
                 $h += 64;
         }
     }
     $displayData = new stdClass();
     $displayData->width = $w;
     $displayData->height = $h;
     $displayData->src = $src;
     switch ($thisFileInfo['fileformat']) {
         case 'asf':
             $layout = $model->getLayout('video-asf');
             break;
         default:
             $layout = $model->getLayout('video');
             break;
     }
     $this->output = $layout->render($displayData);
 }
Beispiel #5
0
function GetMIMEtype($filename)
{
    // include getID3() library (can be in a different directory if full path is specified)
    require_once '../getid3/getid3.php';
    // Initialize getID3 engine
    $getID3 = new getID3();
    $DeterminedMIMEtype = '';
    if ($fp = fopen($filename, 'rb')) {
        $ThisFileInfo = array('avdataoffset' => 0, 'avdataend' => 0);
        getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.tag.id3v2.php', __FILE__, true);
        $tag = new getid3_id3v2($fp, $ThisFileInfo);
        fseek($fp, $ThisFileInfo['avdataoffset'], SEEK_SET);
        $formattest = fread($fp, 16);
        // 16 bytes is sufficient for any format except ISO CD-image
        fclose($fp);
        $DeterminedFormatInfo = $getID3->GetFileFormat($formattest);
        $DeterminedMIMEtype = $DeterminedFormatInfo['mime_type'];
    }
    return $DeterminedMIMEtype;
}
Beispiel #6
0
function GetMIMEtype($filename)
{
    $filename = realpath($filename);
    if (!file_exists($filename)) {
        echo 'File does not exist: "' . htmlentities($filename) . '"<br>';
        return '';
    } elseif (!is_readable($filename)) {
        echo 'File is not readable: "' . htmlentities($filename) . '"<br>';
        return '';
    }
    // include getID3() library (can be in a different directory if full path is specified)
    require_once '../getid3/getid3.php';
    // Initialize getID3 engine
    $getID3 = new getID3();
    $DeterminedMIMEtype = '';
    if ($fp = fopen($filename, 'rb')) {
        $getID3->openfile($filename);
        if (empty($getID3->info['error'])) {
            // ID3v2 is the only tag format that might be prepended in front of files, and it's non-trivial to skip, easier just to parse it and know where to skip to
            getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.tag.id3v2.php', __FILE__, true);
            $getid3_id3v2 = new getid3_id3v2($getID3);
            $getid3_id3v2->Analyze();
            fseek($fp, $getID3->info['avdataoffset'], SEEK_SET);
            $formattest = fread($fp, 16);
            // 16 bytes is sufficient for any format except ISO CD-image
            fclose($fp);
            $DeterminedFormatInfo = $getID3->GetFileFormat($formattest);
            $DeterminedMIMEtype = $DeterminedFormatInfo['mime_type'];
        } else {
            echo 'Failed to getID3->openfile "' . htmlentities($filename) . '"<br>';
        }
    } else {
        echo 'Failed to fopen "' . htmlentities($filename) . '"<br>';
    }
    return $DeterminedMIMEtype;
}
Beispiel #7
0
function kpgenerateid3v2tag($sid)
{
    global $cfg, $phpenv, $setctl;
    if ($cfg['enablegetid3']) {
        $f2 = new file2($sid, true);
        switch (GETID3_V) {
            case 16:
                require_once GETID3_INCLUDEPATH . 'getid3.id3v2.php';
                $data['id3v2']['TIT2'][0]['encodingid'] = 0;
                $data['id3v2']['TIT2'][0]['data'] = $f2->id3['title'];
                $data['id3v2']['TPE1'][0]['encodingid'] = 0;
                $data['id3v2']['TPE1'][0]['data'] = $f2->id3['artist'];
                $data['id3v2']['TALB'][0]['encodingid'] = 0;
                $data['id3v2']['TALB'][0]['data'] = $f2->id3['album'];
                $data['id3v2']['TRCK'][0]['encodingid'] = 0;
                $data['id3v2']['TRCK'][0]['data'] = $f2->id3['track'];
                $data['id3v2']['COM'][0]['encodingid'] = 0;
                $data['id3v2']['COM'][0]['data'] = $f2->id3['comment'];
                $data['id3v2']['TYER'][0]['encodingid'] = 0;
                $data['id3v2']['TYER'][0]['data'] = $f2->id3['year'];
                return GenerateID3v2Tag($data['id3v2'], 3, 0, 0, '', false, false, false);
                break;
            case 19:
            case 17:
                $tagformat = 'UTF-8';
                $major = 3;
                $getID3 = new getID3();
                $getID3->encoding = $tagformat;
                if (!defined('GETID3_INCLUDEPATH')) {
                    define('GETID3_INCLUDEPATH', dirname($cfg['getid3include']) . '/');
                }
                if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.tag.id3v2.php', __FILE__, false) && getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'write.php', __FILE__, false) && getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'write.id3v2.php', __FILE__, false)) {
                    $tagwriter = new getid3_writetags();
                    $tagwriter->tagformats = array('id3v2.3');
                    $tagwriter->filename = $f2->fullpath;
                    if (GETID3_V == 17) {
                        $tagwriter->overwrite_tags = false;
                    }
                    $tagwriter->tag_encoding = $tagformat;
                    $tagwriter->remove_other_tags = false;
                    $TagData['title'][0] = $f2->id3['title'];
                    $TagData['artist'][0] = $f2->id3['artist'];
                    $TagData['album'][0] = $f2->id3['album'];
                    if (vernum($f2->id3['year']) != 0) {
                        $TagData['year'][0] = vernum($f2->id3['year']);
                    }
                    $TagData['comment'][0] = $f2->id3['comment'];
                    $TagData['track'][0] = vernum($f2->id3['track']);
                    if (empty($TagData['title'][0])) {
                        $TagData['title'][0] = $f2->fname;
                    }
                    if (empty($TagData['artist'][0])) {
                        $TagData['artist'][0] = 'Unknown';
                    }
                    if (empty($TagData['album'][0])) {
                        $exp = explode('/', dirname($f2->fullpath));
                        if (count($exp) > 1) {
                            $TagData['album'][0] = $exp[count($exp) - 1];
                        }
                    }
                    $ci = new coverinterface();
                    $ci->setartist($f2->id3['artist'], $f2->id3['album']);
                    $ci->setlocation($f2->drive, $f2->relativepath);
                    if ($ci->coverexists()) {
                        if ($cfg['id3v2albumresize']) {
                            $rs = true;
                        } else {
                            $rs = false;
                        }
                        $imgdata = $ci->getimagedata($rs);
                        if (strlen($imgdata) > 0) {
                            if ($cfg['maxtagimagesize'] == 0 || strlen($imgdata) <= $cfg['maxtagimagesize']) {
                                $TagData['attached_picture'][0]['data'] = $imgdata;
                                $TagData['attached_picture'][0]['picturetypeid'] = 3;
                                $TagData['attached_picture'][0]['encodingid'] = 0;
                                $TagData['attached_picture'][0]['description'] = 'ART';
                                $TagData['attached_picture'][0]['mime'] = 'image/jpeg';
                            }
                        }
                    }
                    $tagwriter->tag_data = $TagData;
                    $id3v2_writer = new getid3_write_id3v2();
                    $id3v2_writer->majorversion = $major;
                    $id3v2_writer->paddedlength = 0;
                    if (($id3v2_writer->tag_data = $tagwriter->FormatDataForID3v2($major)) !== false) {
                        return $id3v2_writer->GenerateID3v2Tag();
                    }
                }
                break;
        }
    }
    return '';
}
 function getid3_shorten(&$fd, &$ThisFileInfo)
 {
     fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
     $ShortenHeader = fread($fd, 8);
     if (substr($ShortenHeader, 0, 4) != 'ajkg') {
         $ThisFileInfo['error'][] = 'Expecting "ajkg" at offset ' . $ThisFileInfo['avdataoffset'] . ', found "' . substr($ShortenHeader, 0, 4) . '"';
         return false;
     }
     $ThisFileInfo['fileformat'] = 'shn';
     $ThisFileInfo['audio']['dataformat'] = 'shn';
     $ThisFileInfo['audio']['lossless'] = true;
     $ThisFileInfo['audio']['bitrate_mode'] = 'vbr';
     $ThisFileInfo['shn']['version'] = getid3_lib::LittleEndian2Int(substr($ShortenHeader, 4, 1));
     fseek($fd, $ThisFileInfo['avdataend'] - 12, SEEK_SET);
     $SeekTableSignatureTest = fread($fd, 12);
     $ThisFileInfo['shn']['seektable']['present'] = (bool) (substr($SeekTableSignatureTest, 4, 8) == 'SHNAMPSK');
     if ($ThisFileInfo['shn']['seektable']['present']) {
         $ThisFileInfo['shn']['seektable']['length'] = getid3_lib::LittleEndian2Int(substr($SeekTableSignatureTest, 0, 4));
         $ThisFileInfo['shn']['seektable']['offset'] = $ThisFileInfo['avdataend'] - $ThisFileInfo['shn']['seektable']['length'];
         fseek($fd, $ThisFileInfo['shn']['seektable']['offset'], SEEK_SET);
         $SeekTableMagic = fread($fd, 4);
         if ($SeekTableMagic != 'SEEK') {
             $ThisFileInfo['error'][] = 'Expecting "SEEK" at offset ' . $ThisFileInfo['shn']['seektable']['offset'] . ', found "' . $SeekTableMagic . '"';
             return false;
         } else {
             // typedef struct tag_TSeekEntry
             // {
             //   unsigned long SampleNumber;
             //   unsigned long SHNFileByteOffset;
             //   unsigned long SHNLastBufferReadPosition;
             //   unsigned short SHNByteGet;
             //   unsigned short SHNBufferOffset;
             //   unsigned short SHNFileBitOffset;
             //   unsigned long SHNGBuffer;
             //   unsigned short SHNBitShift;
             //   long CBuf0[3];
             //   long CBuf1[3];
             //   long Offset0[4];
             //   long Offset1[4];
             // }TSeekEntry;
             $SeekTableData = fread($fd, $ThisFileInfo['shn']['seektable']['length'] - 16);
             $ThisFileInfo['shn']['seektable']['entry_count'] = floor(strlen($SeekTableData) / 80);
             //$ThisFileInfo['shn']['seektable']['entries'] = array();
             //$SeekTableOffset = 0;
             //for ($i = 0; $i < $ThisFileInfo['shn']['seektable']['entry_count']; $i++) {
             //	$SeekTableEntry['sample_number'] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
             //	$SeekTableOffset += 4;
             //	$SeekTableEntry['shn_file_byte_offset'] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
             //	$SeekTableOffset += 4;
             //	$SeekTableEntry['shn_last_buffer_read_position'] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
             //	$SeekTableOffset += 4;
             //	$SeekTableEntry['shn_byte_get'] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 2));
             //	$SeekTableOffset += 2;
             //	$SeekTableEntry['shn_buffer_offset'] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 2));
             //	$SeekTableOffset += 2;
             //	$SeekTableEntry['shn_file_bit_offset'] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 2));
             //	$SeekTableOffset += 2;
             //	$SeekTableEntry['shn_gbuffer'] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
             //	$SeekTableOffset += 4;
             //	$SeekTableEntry['shn_bit_shift'] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 2));
             //	$SeekTableOffset += 2;
             //	for ($j = 0; $j < 3; $j++) {
             //		$SeekTableEntry['cbuf0'][$j] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
             //		$SeekTableOffset += 4;
             //	}
             //	for ($j = 0; $j < 3; $j++) {
             //		$SeekTableEntry['cbuf1'][$j] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
             //		$SeekTableOffset += 4;
             //	}
             //	for ($j = 0; $j < 4; $j++) {
             //		$SeekTableEntry['offset0'][$j] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
             //		$SeekTableOffset += 4;
             //	}
             //	for ($j = 0; $j < 4; $j++) {
             //		$SeekTableEntry['offset1'][$j] = getid3_lib::LittleEndian2Int(substr($SeekTableData, $SeekTableOffset, 4));
             //		$SeekTableOffset += 4;
             //	}
             //
             //	$ThisFileInfo['shn']['seektable']['entries'][] = $SeekTableEntry;
             //}
         }
     }
     if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) {
         $ThisFileInfo['error'][] = 'PHP running in Safe Mode - backtick operator not available, cannot run shntool to analyze Shorten files';
         return false;
     }
     if (GETID3_OS_ISWINDOWS) {
         $RequiredFiles = array('shorten.exe', 'cygwin1.dll', 'head.exe');
         foreach ($RequiredFiles as $required_file) {
             if (!is_readable(GETID3_HELPERAPPSDIR . $required_file)) {
                 $ThisFileInfo['error'][] = GETID3_HELPERAPPSDIR . $required_file . ' does not exist';
                 return false;
             }
         }
         $commandline = GETID3_HELPERAPPSDIR . 'shorten.exe -x "' . $ThisFileInfo['filenamepath'] . '" - | ' . GETID3_HELPERAPPSDIR . 'head.exe -c 64';
         $commandline = str_replace('/', '\\', $commandline);
     } else {
         static $shorten_present;
         if (!isset($shorten_present)) {
             $shorten_present = file_exists('/usr/local/bin/shorten') || `which shorten`;
         }
         if (!$shorten_present) {
             $ThisFileInfo['error'][] = 'shorten binary was not found in path or /usr/local/bin';
             return false;
         }
         $commandline = (file_exists('/usr/local/bin/shorten') ? '/usr/local/bin/' : '') . 'shorten -x ' . escapeshellarg($ThisFileInfo['filenamepath']) . ' - | head -c 64';
     }
     $output = `{$commandline}`;
     if (!empty($output) && substr($output, 12, 4) == 'fmt ') {
         getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio-video.riff.php', __FILE__, true);
         $fmt_size = getid3_lib::LittleEndian2Int(substr($output, 16, 4));
         $DecodedWAVFORMATEX = getid3_riff::RIFFparseWAVEFORMATex(substr($output, 20, $fmt_size));
         $ThisFileInfo['audio']['channels'] = $DecodedWAVFORMATEX['channels'];
         $ThisFileInfo['audio']['bits_per_sample'] = $DecodedWAVFORMATEX['bits_per_sample'];
         $ThisFileInfo['audio']['sample_rate'] = $DecodedWAVFORMATEX['sample_rate'];
         if (substr($output, 20 + $fmt_size, 4) == 'data') {
             $ThisFileInfo['playtime_seconds'] = getid3_lib::LittleEndian2Int(substr($output, 20 + 4 + $fmt_size, 4)) / $DecodedWAVFORMATEX['raw']['nAvgBytesPerSec'];
         } else {
             $ThisFileInfo['error'][] = 'shorten failed to decode DATA chunk to expected location, cannot determine playtime';
             return false;
         }
         $ThisFileInfo['audio']['bitrate'] = ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) / $ThisFileInfo['playtime_seconds'] * 8;
     } else {
         $ThisFileInfo['error'][] = 'shorten failed to decode file to WAV for parsing';
         return false;
     }
     return true;
 }
 function getid3_lyrics3(&$fd, &$ThisFileInfo)
 {
     // http://www.volweb.cz/str/tags.htm
     fseek($fd, 0 - 128 - 9 - 6, SEEK_END);
     // end - ID3v1 - LYRICSEND - [Lyrics3size]
     $lyrics3_id3v1 = fread($fd, 128 + 9 + 6);
     $lyrics3lsz = substr($lyrics3_id3v1, 0, 6);
     // Lyrics3size
     $lyrics3end = substr($lyrics3_id3v1, 6, 9);
     // LYRICSEND or LYRICS200
     $id3v1tag = substr($lyrics3_id3v1, 15, 128);
     // ID3v1
     if ($lyrics3end == 'LYRICSEND') {
         // Lyrics3v1, ID3v1, no APE
         $lyrics3size = 5100;
         $lyrics3offset = $ThisFileInfo['filesize'] - 128 - $lyrics3size;
         $lyrics3version = 1;
     } elseif ($lyrics3end == 'LYRICS200') {
         // Lyrics3v2, ID3v1, no APE
         // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200'
         $lyrics3size = $lyrics3lsz + 6 + strlen('LYRICS200');
         $lyrics3offset = $ThisFileInfo['filesize'] - 128 - $lyrics3size;
         $lyrics3version = 2;
     } elseif (substr(strrev($lyrics3_id3v1), 0, 9) == strrev('LYRICSEND')) {
         // Lyrics3v1, no ID3v1, no APE
         $lyrics3size = 5100;
         $lyrics3offset = $ThisFileInfo['filesize'] - $lyrics3size;
         $lyrics3version = 1;
         $lyrics3offset = $ThisFileInfo['filesize'] - $lyrics3size;
     } elseif (substr(strrev($lyrics3_id3v1), 0, 9) == strrev('LYRICS200')) {
         // Lyrics3v2, no ID3v1, no APE
         $lyrics3size = strrev(substr(strrev($lyrics3_id3v1), 9, 6)) + 6 + strlen('LYRICS200');
         // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200'
         $lyrics3offset = $ThisFileInfo['filesize'] - $lyrics3size;
         $lyrics3version = 2;
     } else {
         if (isset($ThisFileInfo['ape']['tag_offset_start']) && $ThisFileInfo['ape']['tag_offset_start'] > 15) {
             fseek($fd, $ThisFileInfo['ape']['tag_offset_start'] - 15, SEEK_SET);
             $lyrics3lsz = fread($fd, 6);
             $lyrics3end = fread($fd, 9);
             if ($lyrics3end == 'LYRICSEND') {
                 // Lyrics3v1, APE, maybe ID3v1
                 $lyrics3size = 5100;
                 $lyrics3offset = $ThisFileInfo['ape']['tag_offset_start'] - $lyrics3size;
                 $ThisFileInfo['avdataend'] = $lyrics3offset;
                 $lyrics3version = 1;
                 $ThisFileInfo['warning'][] = 'APE tag located after Lyrics3, will probably break Lyrics3 compatability';
             } elseif ($lyrics3end == 'LYRICS200') {
                 // Lyrics3v2, APE, maybe ID3v1
                 $lyrics3size = $lyrics3lsz + 6 + strlen('LYRICS200');
                 // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200'
                 $lyrics3offset = $ThisFileInfo['ape']['tag_offset_start'] - $lyrics3size;
                 $lyrics3version = 2;
                 $ThisFileInfo['warning'][] = 'APE tag located after Lyrics3, will probably break Lyrics3 compatability';
             }
         }
     }
     if (isset($lyrics3offset)) {
         $ThisFileInfo['avdataend'] = $lyrics3offset;
         $this->getLyrics3Data($ThisFileInfo, $fd, $lyrics3offset, $lyrics3version, $lyrics3size);
         if (!isset($ThisFileInfo['ape'])) {
             $GETID3_ERRORARRAY =& $ThisFileInfo['warning'];
             if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.tag.apetag.php', __FILE__, false)) {
                 $tag = new getid3_apetag($fd, $ThisFileInfo, $ThisFileInfo['lyrics3']['tag_offset_start']);
             }
         }
     }
     return true;
 }
 public function Analyze()
 {
     $info =& $this->getid3->info;
     // parse container
     try {
         $this->parseEBML($info);
     } catch (Exception $e) {
         $info['error'][] = 'EBML parser: ' . $e->getMessage();
     }
     // calculate playtime
     if (isset($info['matroska']['info']) && is_array($info['matroska']['info'])) {
         foreach ($info['matroska']['info'] as $key => $infoarray) {
             if (isset($infoarray['Duration'])) {
                 // TimecodeScale is how many nanoseconds each Duration unit is
                 $info['playtime_seconds'] = $infoarray['Duration'] * ((isset($infoarray['TimecodeScale']) ? $infoarray['TimecodeScale'] : 1000000) / 1000000000);
                 break;
             }
         }
     }
     // extract tags
     if (isset($info['matroska']['tags']) && is_array($info['matroska']['tags'])) {
         foreach ($info['matroska']['tags'] as $key => $infoarray) {
             $this->ExtractCommentsSimpleTag($infoarray);
         }
     }
     // process tracks
     if (isset($info['matroska']['tracks']['tracks']) && is_array($info['matroska']['tracks']['tracks'])) {
         foreach ($info['matroska']['tracks']['tracks'] as $key => $trackarray) {
             $track_info = array();
             $track_info['dataformat'] = self::MatroskaCodecIDtoCommonName($trackarray['CodecID']);
             $track_info['default'] = isset($trackarray['FlagDefault']) ? $trackarray['FlagDefault'] : true;
             if (isset($trackarray['Name'])) {
                 $track_info['name'] = $trackarray['Name'];
             }
             switch ($trackarray['TrackType']) {
                 case 1:
                     // Video
                     $track_info['resolution_x'] = $trackarray['PixelWidth'];
                     $track_info['resolution_y'] = $trackarray['PixelHeight'];
                     if (isset($trackarray['DisplayWidth'])) {
                         $track_info['display_x'] = $trackarray['DisplayWidth'];
                     }
                     if (isset($trackarray['DisplayHeight'])) {
                         $track_info['display_y'] = $trackarray['DisplayHeight'];
                     }
                     if (isset($trackarray['DefaultDuration'])) {
                         $track_info['frame_rate'] = round(1000000000 / $trackarray['DefaultDuration'], 3);
                     }
                     //if (isset($trackarray['CodecName']))       { $track_info['codec']      = $trackarray['CodecName']; }
                     switch ($trackarray['CodecID']) {
                         case 'V_MS/VFW/FOURCC':
                             if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio-video.riff.php', __FILE__, false)) {
                                 $this->getid3->warning('Unable to parse codec private data [' . basename(__FILE__) . ':' . __LINE__ . '] because cannot include "module.audio-video.riff.php"');
                                 break;
                             }
                             $parsed = getid3_riff::ParseBITMAPINFOHEADER($trackarray['CodecPrivate']);
                             $track_info['codec'] = getid3_riff::RIFFfourccLookup($parsed['fourcc']);
                             $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $parsed;
                             break;
                     }
                     $info['video']['streams'][] = $track_info;
                     break;
                 case 2:
                     // Audio
                     $track_info['sample_rate'] = isset($trackarray['SamplingFrequency']) ? $trackarray['SamplingFrequency'] : 8000.0;
                     $track_info['channels'] = isset($trackarray['Channels']) ? $trackarray['Channels'] : 1;
                     $track_info['language'] = isset($trackarray['Language']) ? $trackarray['Language'] : 'eng';
                     if (isset($trackarray['BitDepth'])) {
                         $track_info['bits_per_sample'] = $trackarray['BitDepth'];
                     }
                     //if (isset($trackarray['CodecName'])) { $track_info['codec']           = $trackarray['CodecName']; }
                     switch ($trackarray['CodecID']) {
                         case 'A_PCM/INT/LIT':
                         case 'A_PCM/INT/BIG':
                             $track_info['bitrate'] = $trackarray['SamplingFrequency'] * $trackarray['Channels'] * $trackarray['BitDepth'];
                             break;
                         case 'A_AC3':
                         case 'A_DTS':
                         case 'A_MPEG/L3':
                             //case 'A_FLAC':
                             if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.' . $track_info['dataformat'] . '.php', __FILE__, false)) {
                                 $this->getid3->warning('Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because cannot include "module.audio.' . $track_info['dataformat'] . '.php"');
                                 break;
                             }
                             if (!isset($info['matroska']['track_data_offsets'][$trackarray['TrackNumber']])) {
                                 $this->getid3->warning('Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because $info[matroska][track_data_offsets][' . $trackarray['TrackNumber'] . '] not set');
                                 break;
                             }
                             // create temp instance
                             $getid3_temp = new getID3();
                             $getid3_temp->openfile($this->getid3->filename);
                             $getid3_temp->info['avdataoffset'] = $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['offset'];
                             if ($track_info['dataformat'] == 'mp3' || $track_info['dataformat'] == 'flac') {
                                 $getid3_temp->info['avdataend'] = $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['offset'] + $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['length'];
                             }
                             // analyze
                             $class = 'getid3_' . $track_info['dataformat'];
                             $header_data_key = $track_info['dataformat'] == 'mp3' ? 'mpeg' : $track_info['dataformat'];
                             $getid3_audio = new $class($getid3_temp);
                             if ($track_info['dataformat'] == 'mp3') {
                                 $getid3_audio->allow_bruteforce = true;
                             }
                             if ($track_info['dataformat'] == 'flac') {
                                 $getid3_audio->AnalyzeString($trackarray['CodecPrivate']);
                             } else {
                                 $getid3_audio->Analyze();
                             }
                             if (!empty($getid3_temp->info[$header_data_key])) {
                                 unset($getid3_temp->info[$header_data_key]['GETID3_VERSION']);
                                 $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info[$header_data_key];
                                 if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
                                     foreach ($getid3_temp->info['audio'] as $key => $value) {
                                         $track_info[$key] = $value;
                                     }
                                 }
                             } else {
                                 $this->getid3->warning('Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because ' . $class . '::Analyze() failed at offset ' . $getid3_temp->info['avdataoffset']);
                             }
                             // copy errors and warnings
                             if (!empty($getid3_temp->info['error'])) {
                                 foreach ($getid3_temp->info['error'] as $newerror) {
                                     $this->getid3->warning($class . '() says: [' . $newerror . ']');
                                 }
                             }
                             if (!empty($getid3_temp->info['warning'])) {
                                 foreach ($getid3_temp->info['warning'] as $newerror) {
                                     if ($track_info['dataformat'] == 'mp3' && preg_match('/^Probable truncated file: expecting \\d+ bytes of audio data, only found \\d+ \\(short by \\d+ bytes\\)$/', $newerror)) {
                                         // LAME/Xing header is probably set, but audio data is chunked into Matroska file and near-impossible to verify if audio stream is complete, so ignore useless warning
                                         continue;
                                     }
                                     $this->getid3->warning($class . '() says: [' . $newerror . ']');
                                 }
                             }
                             unset($getid3_temp, $getid3_audio);
                             break;
                         case 'A_AAC':
                         case 'A_AAC/MPEG2/LC':
                         case 'A_AAC/MPEG4/LC':
                         case 'A_AAC/MPEG4/LC/SBR':
                             $this->getid3->warning($trackarray['CodecID'] . ' audio data contains no header, audio/video bitrates can\'t be calculated');
                             break;
                         case 'A_VORBIS':
                             if (!isset($trackarray['CodecPrivate'])) {
                                 $this->getid3->warning('Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because CodecPrivate data not set');
                                 break;
                             }
                             $vorbis_offset = strpos($trackarray['CodecPrivate'], 'vorbis', 1);
                             if ($vorbis_offset === false) {
                                 $this->getid3->warning('Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because CodecPrivate data does not contain "vorbis" keyword');
                                 break;
                             }
                             $vorbis_offset -= 1;
                             if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.ogg.php', __FILE__, false)) {
                                 $this->getid3->warning('Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because cannot include "module.audio.ogg.php"');
                             }
                             // create temp instance
                             $getid3_temp = new getID3();
                             $getid3_temp->openfile($this->getid3->filename);
                             // analyze
                             $getid3_ogg = new getid3_ogg($getid3_temp);
                             $oggpageinfo['page_seqno'] = 0;
                             $getid3_ogg->ParseVorbisPageHeader($trackarray['CodecPrivate'], $vorbis_offset, $oggpageinfo);
                             if (!empty($getid3_temp->info['ogg'])) {
                                 $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info['ogg'];
                                 if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
                                     foreach ($getid3_temp->info['audio'] as $key => $value) {
                                         $track_info[$key] = $value;
                                     }
                                 }
                             }
                             // copy errors and warnings
                             if (!empty($getid3_temp->info['error'])) {
                                 foreach ($getid3_temp->info['error'] as $newerror) {
                                     $this->getid3->warning('getid3_ogg() says: [' . $newerror . ']');
                                 }
                             }
                             if (!empty($getid3_temp->info['warning'])) {
                                 foreach ($getid3_temp->info['warning'] as $newerror) {
                                     $this->getid3->warning('getid3_ogg() says: [' . $newerror . ']');
                                 }
                             }
                             if (!empty($getid3_temp->info['ogg']['bitrate_nominal'])) {
                                 $track_info['bitrate'] = $getid3_temp->info['ogg']['bitrate_nominal'];
                             }
                             unset($getid3_temp, $getid3_ogg, $oggpageinfo, $vorbis_offset);
                             break;
                         case 'A_MS/ACM':
                             if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio-video.riff.php', __FILE__, false)) {
                                 $this->getid3->warning('Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because cannot include "module.audio-video.riff.php"');
                                 break;
                             }
                             $parsed = getid3_riff::RIFFparseWAVEFORMATex($trackarray['CodecPrivate']);
                             foreach ($parsed as $key => $value) {
                                 if ($key != 'raw') {
                                     $track_info[$key] = $value;
                                 }
                             }
                             $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $parsed;
                             break;
                         default:
                             $this->getid3->warning('Unhandled audio type "' . (isset($trackarray['CodecID']) ? $trackarray['CodecID'] : '') . '"');
                     }
                     $info['audio']['streams'][] = $track_info;
                     break;
             }
         }
         if (!empty($info['video']['streams'])) {
             $info['video'] = self::getDefaultStreamInfo($info['video']['streams']);
         }
         if (!empty($info['audio']['streams'])) {
             $info['audio'] = self::getDefaultStreamInfo($info['audio']['streams']);
         }
     }
     // determine mime type
     if (!empty($info['video']['streams'])) {
         $info['mime_type'] = $info['matroska']['doctype'] == 'webm' ? 'video/webm' : 'video/x-matroska';
     } elseif (!empty($info['audio']['streams'])) {
         $info['mime_type'] = $info['matroska']['doctype'] == 'webm' ? 'audio/webm' : 'audio/x-matroska';
     } elseif (isset($info['mime_type'])) {
         unset($info['mime_type']);
     }
     return true;
 }
/////////////////////////////////////////////////////////////////
/// getID3() by James Heinrich <*****@*****.**>               //
//  available at http://getid3.sourceforge.net                 //
//            or http://www.getid3.org                         //
//          also https://github.com/JamesHeinrich/getID3       //
/////////////////////////////////////////////////////////////////
// See readme.txt for more details                             //
/////////////////////////////////////////////////////////////////
//                                                             //
// module.audio.ogg.php                                        //
// module for analyzing Ogg Vorbis, OggFLAC and Speex files    //
// dependencies: module.audio.flac.php                         //
//                                                            ///
/////////////////////////////////////////////////////////////////
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.flac.php', __FILE__, true);
class getid3_ogg extends getid3_handler
{
    // http://xiph.org/vorbis/doc/Vorbis_I_spec.html
    public function Analyze()
    {
        $info =& $this->getid3->info;
        $info['fileformat'] = 'ogg';
        // Warn about illegal tags - only vorbiscomments are allowed
        if (isset($info['id3v2'])) {
            $info['warning'][] = 'Illegal ID3v2 tag present.';
        }
        if (isset($info['id3v1'])) {
            $info['warning'][] = 'Illegal ID3v1 tag present.';
        }
        if (isset($info['ape'])) {
 function getid3_jpg(&$fd, &$ThisFileInfo)
 {
     $ThisFileInfo['fileformat'] = 'jpg';
     $ThisFileInfo['video']['dataformat'] = 'jpg';
     $ThisFileInfo['video']['lossless'] = false;
     $ThisFileInfo['video']['bits_per_sample'] = 24;
     $ThisFileInfo['video']['pixel_aspect_ratio'] = (double) 1;
     fseek($fd, $ThisFileInfo['avdataoffset'], SEEK_SET);
     $imageinfo = array();
     list($width, $height, $type) = getid3_lib::GetDataImageSize(fread($fd, $ThisFileInfo['filesize']), $imageinfo);
     if (isset($imageinfo['APP13'])) {
         // http://php.net/iptcparse
         // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/IPTC.html
         $iptc_parsed = iptcparse($imageinfo['APP13']);
         if (is_array($iptc_parsed)) {
             foreach ($iptc_parsed as $iptc_key_raw => $iptc_values) {
                 list($iptc_record, $iptc_tagkey) = explode('#', $iptc_key_raw);
                 $iptc_tagkey = intval(ltrim($iptc_tagkey, '0'));
                 foreach ($iptc_values as $key => $value) {
                     $IPTCrecordName = $this->IPTCrecordName($iptc_record);
                     $IPTCrecordTagName = $this->IPTCrecordTagName($iptc_record, $iptc_tagkey);
                     if (isset($ThisFileInfo['iptc'][$IPTCrecordName][$IPTCrecordTagName])) {
                         $ThisFileInfo['iptc'][$IPTCrecordName][$IPTCrecordTagName][] = $value;
                     } else {
                         $ThisFileInfo['iptc'][$IPTCrecordName][$IPTCrecordTagName] = array($value);
                     }
                 }
             }
         }
     }
     $returnOK = false;
     switch ($type) {
         case IMG_JPG:
             $ThisFileInfo['video']['resolution_x'] = $width;
             $ThisFileInfo['video']['resolution_y'] = $height;
             if (isset($imageinfo['APP1'])) {
                 if (version_compare(phpversion(), '4.2.0', '>=')) {
                     if (function_exists('exif_read_data')) {
                         if (substr($imageinfo['APP1'], 0, 4) == 'Exif') {
                             ob_start();
                             $ThisFileInfo['jpg']['exif'] = exif_read_data($ThisFileInfo['filenamepath'], '', true, false);
                             $errors = ob_get_contents();
                             if ($errors) {
                                 $ThisFileInfo['warning'][] = strip_tags($errors);
                                 //unset($ThisFileInfo['jpg']['exif']);
                             }
                             ob_end_clean();
                         } else {
                             $ThisFileInfo['warning'][] = 'exif_read_data() cannot parse non-EXIF data in APP1 (expected "Exif", found "' . substr($imageinfo['APP1'], 0, 4) . '")';
                         }
                     } else {
                         $ThisFileInfo['warning'][] = 'EXIF parsing only available when ' . (GETID3_OS_ISWINDOWS ? 'php_exif.dll enabled' : 'compiled with --enable-exif');
                     }
                 } else {
                     $ThisFileInfo['warning'][] = 'EXIF parsing only available in PHP v4.2.0 and higher compiled with --enable-exif (or php_exif.dll enabled for Windows). You are using PHP v' . phpversion();
                 }
             }
             $returnOK = true;
             break;
         default:
             break;
     }
     $cast_as_appropriate_keys = array('EXIF', 'IFD0', 'THUMBNAIL');
     foreach ($cast_as_appropriate_keys as $exif_key) {
         if (isset($ThisFileInfo['jpg']['exif'][$exif_key])) {
             foreach ($ThisFileInfo['jpg']['exif'][$exif_key] as $key => $value) {
                 $ThisFileInfo['jpg']['exif'][$exif_key][$key] = $this->CastAsAppropriate($value);
             }
         }
     }
     if (isset($ThisFileInfo['jpg']['exif']['GPS'])) {
         if (isset($ThisFileInfo['jpg']['exif']['GPS']['GPSVersion'])) {
             for ($i = 0; $i < 4; $i++) {
                 $version_subparts[$i] = ord(substr($ThisFileInfo['jpg']['exif']['GPS']['GPSVersion'], $i, 1));
             }
             $ThisFileInfo['jpg']['exif']['GPS']['computed']['version'] = 'v' . implode('.', $version_subparts);
         }
         if (isset($ThisFileInfo['jpg']['exif']['GPS']['GPSDateStamp'])) {
             $explodedGPSDateStamp = explode(':', $ThisFileInfo['jpg']['exif']['GPS']['GPSDateStamp']);
             $computed_time[5] = isset($explodedGPSDateStamp[0]) ? $explodedGPSDateStamp[0] : '';
             $computed_time[3] = isset($explodedGPSDateStamp[1]) ? $explodedGPSDateStamp[1] : '';
             $computed_time[4] = isset($explodedGPSDateStamp[2]) ? $explodedGPSDateStamp[2] : '';
             if (function_exists('date_default_timezone_set')) {
                 date_default_timezone_set('UTC');
             } else {
                 ini_set('date.timezone', 'UTC');
             }
             $computed_time = array(0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0);
             if (isset($ThisFileInfo['jpg']['exif']['GPS']['GPSTimeStamp']) && is_array($ThisFileInfo['jpg']['exif']['GPS']['GPSTimeStamp'])) {
                 foreach ($ThisFileInfo['jpg']['exif']['GPS']['GPSTimeStamp'] as $key => $value) {
                     $computed_time[$key] = getid3_lib::DecimalizeFraction($value);
                 }
             }
             $ThisFileInfo['jpg']['exif']['GPS']['computed']['timestamp'] = mktime($computed_time[0], $computed_time[1], $computed_time[2], $computed_time[3], $computed_time[4], $computed_time[5]);
         }
         if (isset($ThisFileInfo['jpg']['exif']['GPS']['GPSLatitude']) && is_array($ThisFileInfo['jpg']['exif']['GPS']['GPSLatitude'])) {
             $direction_multiplier = isset($ThisFileInfo['jpg']['exif']['GPS']['GPSLatitudeRef']) && $ThisFileInfo['jpg']['exif']['GPS']['GPSLatitudeRef'] == 'S' ? -1 : 1;
             foreach ($ThisFileInfo['jpg']['exif']['GPS']['GPSLatitude'] as $key => $value) {
                 $computed_latitude[$key] = getid3_lib::DecimalizeFraction($value);
             }
             $ThisFileInfo['jpg']['exif']['GPS']['computed']['latitude'] = $direction_multiplier * ($computed_latitude[0] + $computed_latitude[1] / 60 + $computed_latitude[2] / 3600);
         }
         if (isset($ThisFileInfo['jpg']['exif']['GPS']['GPSLongitude']) && is_array($ThisFileInfo['jpg']['exif']['GPS']['GPSLongitude'])) {
             $direction_multiplier = isset($ThisFileInfo['jpg']['exif']['GPS']['GPSLongitudeRef']) && $ThisFileInfo['jpg']['exif']['GPS']['GPSLongitudeRef'] == 'W' ? -1 : 1;
             foreach ($ThisFileInfo['jpg']['exif']['GPS']['GPSLongitude'] as $key => $value) {
                 $computed_longitude[$key] = getid3_lib::DecimalizeFraction($value);
             }
             $ThisFileInfo['jpg']['exif']['GPS']['computed']['longitude'] = $direction_multiplier * ($computed_longitude[0] + $computed_longitude[1] / 60 + $computed_longitude[2] / 3600);
         }
         if (isset($ThisFileInfo['jpg']['exif']['GPS']['GPSAltitude'])) {
             $direction_multiplier = isset($ThisFileInfo['jpg']['exif']['GPS']['GPSAltitudeRef']) && $ThisFileInfo['jpg']['exif']['GPS']['GPSAltitudeRef'] === chr(1) ? -1 : 1;
             $ThisFileInfo['jpg']['exif']['GPS']['computed']['altitude'] = $direction_multiplier * getid3_lib::DecimalizeFraction($ThisFileInfo['jpg']['exif']['GPS']['GPSAltitude']);
         }
     }
     if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.tag.xmp.php', __FILE__, false)) {
         if (isset($ThisFileInfo['filenamepath'])) {
             $image_xmp = new Image_XMP($ThisFileInfo['filenamepath']);
             $xmp_raw = $image_xmp->getAllTags();
             foreach ($xmp_raw as $key => $value) {
                 list($subsection, $tagname) = explode(':', $key);
                 $ThisFileInfo['xmp'][$subsection][$tagname] = $this->CastAsAppropriate($value);
             }
         }
     }
     if (!$returnOK) {
         unset($ThisFileInfo['fileformat']);
         return false;
     }
     return true;
 }
Beispiel #13
0
 /**
  * @param object element model
  * @param object element params
  * @param string row data for this element
  */
 function render(&$model, &$params, $file)
 {
     $fbConfig =& JComponentHelper::getParams('com_fabrik');
     ini_set('display_errors', true);
     require_once COM_FABRIK_FRONTEND . DS . 'libs' . DS . 'getid3' . DS . 'getid3' . DS . 'getid3.php';
     require_once COM_FABRIK_FRONTEND . DS . 'libs' . DS . 'getid3' . DS . 'getid3' . DS . 'getid3.lib.php';
     getid3_lib::IncludeDependency(COM_FABRIK_FRONTEND . DS . 'libs' . DS . 'getid3' . DS . 'getid3' . DS . 'extension.cache.mysql.php', __FILE__, true);
     $config =& JFactory::getConfig();
     $host = $config->getValue('host');
     $database = $config->getValue('db');
     $username = $config->getValue('user');
     $password = $config->getValue('password');
     $getID3 = new getID3_cached_mysql($host, $database, $username, $password);
     // Analyze file and store returned data in $ThisFileInfo
     $relPath = str_replace("\\", "/", JPATH_SITE . $file);
     $thisFileInfo = $getID3->analyze($relPath);
     //var_dump($relPath, $thisFileInfo);
     $w = $params->get('fu_main_max_width', 0);
     $h = $params->get('fu_main_max_height', 0);
     if (is_array($thisFileInfo)) {
         if (array_key_exists('swf', $thisFileInfo)) {
             if ($thisFileInfo['swf']['header']['frame_width'] < $w || $thisFileInfo['swf']['header']['frame_height'] < $h) {
                 $w = $thisFileInfo['swf']['header']['frame_width'];
                 $h = $thisFileInfo['swf']['header']['frame_height'];
             }
         }
     }
     if ($w <= 0 || $h <= 0) {
         $w = 800;
         $h = 600;
     }
     // $$$ hugh - if they've enabled thumbnails, for Flash content we'll take that to mean they don't
     // want to play the content inline in the table, and use mediabox (if available) to open it instead.
     if (!$model->_inDetailedView && $fbConfig->get('use_mediabox', true) && FabrikWorker::getMooVersion() == 1 && $params->get('make_thumbnail', false)) {
         $element =& $model->getElement();
         // @TODO - work out how to do thumbnails
         // $$$ hugh - thought about using thumbed-down embedded Flash as
         // thumbnail, but really need to avoid having to download every flash in
         // the table on page load!  But just doesn't seem to be a way of getting
         // a thumbnail from a Flash.  For now, just use a default "Here Be Flash"
         // icon for the thumb.  Might be nice to add 'icon to use' option for Upload
         // element, so if it isn't an image type, you can point at another element on the form,
         // (either and Upload or an Image) and use that as the thumb for this content.
         /*
         $thumb_w = $params->get('thumb_max_width');
         $thumb_h = $params->get('thumb_max_height');
         $file = str_replace("\\", "/", COM_FABRIK_LIVESITE  . $file);
         $this->output = "<object width=\"$w\" height=\"$h\">
         <param name=\"movie\" value=\"$file\">
         <embed src=\"$file\" width=\"$thumb_w\" height=\"$thumb_h\">
         </embed>
         </object>";
         */
         $thumb_dir = $params->get('thumb_dir');
         if (!empty($thumb_dir)) {
             $file = str_replace("\\", "/", $file);
             $pathinfo = pathinfo($file);
             // $$$ hugh - apparently filename ocnstant only added in PHP 5.2
             if (!isset($pathinfo['filename'])) {
                 $pathinfo['filename'] = explode('.', $pathinfo['basename']);
                 $pathinfo['filename'] = $pathinfo['filename'][0];
             }
             $thumb_path = COM_FABRIK_BASE . DS . $thumb_dir . DS . $pathinfo['filename'] . '.png';
             if (JFile::exists($thumb_path)) {
                 $thumb_file = COM_FABRIK_LIVESITE . $thumb_dir . '/' . $pathinfo['filename'] . '.png';
             } else {
                 $thumb_file = COM_FABRIK_LIVESITE . "media/com_fabrik/images/flash.jpg";
             }
         } else {
             $thumb_file = COM_FABRIK_LIVESITE . "media/com_fabrik/images/flash.jpg";
         }
         $file = str_replace("\\", "/", COM_FABRIK_LIVESITE . $file);
         $this->output .= "<a href=\"{$file}\" rel=\"lightbox[flash {$w} {$h}]\"><img src=\"{$thumb_file}\" alt=\"Full Size\" /></a>";
     } else {
         if ($model->_inDetailedView) {
             $file = str_replace("\\", "/", COM_FABRIK_LIVESITE . $file);
             $this->output .= "<object width=\"{$w}\" height=\"{$h}\">\n\t\t\t\t<param name=\"movie\" value=\"{$file}\">\n\t\t\t\t<embed src=\"{$file}\" width=\"{$w}\" height=\"{$h}\">\n\t\t\t\t</embed>\n\t\t\t\t</object>";
         } else {
             $file = str_replace("\\", "/", COM_FABRIK_LIVESITE . $file);
             $this->output .= "<object width=\"{$w}\" height=\"{$h}\">\n\t\t\t\t<param name=\"movie\" value=\"{$file}\">\n\t\t\t\t<embed src=\"{$file}\" width=\"{$w}\" height=\"{$h}\">\n\t\t\t\t</embed>\n\t\t\t\t</object>";
         }
     }
     //}
 }
Beispiel #14
0
    public function home()
    {
        global $core;
        error_reporting(0);
        $v = $this->__(w('v'));
        if (!$v['v']) {
            $sql = 'SELECT media_id
				FROM _bio_media
				WHERE media_type = ?
					AND media_mp3 = ?
				LIMIT 1';
            $v['v'] = _field(sql_filter($sql, 1, 0), 'media_id', 0);
        }
        $tag_format = 'UTF-8';
        $relative_path = '/data/artists/%s/media/';
        $absolute_path = '/var/www/vhosts/rockrepublik.net/www' . $relative_path;
        $sql = 'SELECT m.*, b.bio_id, b.bio_name
			FROM _bio_media m
			LEFT JOIN _bio b ON m.media_bio = b.bio_id
			WHERE m.media_id = ?';
        //$spaths = '/data/artists/' . $songd['ub'] . '/media/';
        //$spath = '/var/www/vhosts/rockrepublik.net/httpdocs' . $spaths;
        if ($media = _fieldrow(sql_filter($sql, $v['v']))) {
            $row_relative = sprintf($relative_path, $media['bio_id']);
            $row_absolute = $absolute_path . $row_relative;
            $row_wma = $row_absolute . $media['media_id'] . '.wma';
            $row_mp3 = $row_absolute . $media['media_id'] . '.mp3';
            $rel_wma = '.' . $row_relative . $media['media_id'] . '.wma';
            $rel_mp3 = '.' . $row_relative . $media['media_id'] . '.mp3';
            if (@file_exists($rel_wma) && !@file_exists($rel_mp3) && !$media['media_mp3']) {
                exec('ffmpeg -i ' . $row_wma . ' -vn -ar 44100 -ac 2 -ab 64kb -f mp3 ' . $row_mp3);
                include_once XFS . XCOR . 'getid3/getid3.php';
                $getID3 = new getID3();
                $getID3->setOption(array('encoding' => $tag_format));
                getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'write.php', __FILE__, true);
                $tagwriter = new getid3_writetags();
                $tagwriter->filename = getid3_lib::SafeStripSlashes($row_mp3);
                $tagwriter->tagformats = array('id3v1');
                $tagwriter->overwrite_tags = true;
                $tagwriter->tag_encoding = $tag_format;
                $tagwriter->remove_other_tags = true;
                $tag_comment = 'Visita www.rockrepublik.net';
                $media['album'] = !empty($media['media_album']) ? $media['media_album'] : 'Single';
                $media['genre'] = !empty($media['media_genre']) ? $media['media_genre'] : 'Rock';
                $media_f = array('title', 'name', 'album', 'genre');
                foreach ($media_f as $mr) {
                    $media['media_' . $mr] = getid3_lib::SafeStripSlashes(utf8_encode(html_entity_decode($media['media_' . $mr])));
                }
                $tagwriter->tag_data = array('title' => array($media['media_title']), 'artist' => array($media['media_name']), 'album' => array($media['media_album']), 'year' => array(getid3_lib::SafeStripSlashes($media['media_year'])), 'genre' => array($media['media_genre']), 'comment' => array(getid3_lib::SafeStripSlashes($tag_comment)), 'tracknumber' => array(''));
                $tagwriter->WriteTags();
                $sql = 'UPDATE _bio_media SET media_mp3 = ?
					WHERE media_id = ?';
                _sql(sql_filter($sql, 1, $media['media_id']));
                $fp = @fopen('./conv.txt', 'a+');
                fwrite($fp, $row_mp3 . "\n");
                fclose($fp);
            }
            if (!@file_exists($rel_wma)) {
                $sql = 'UPDATE _bio_media SET media_mp3 = ?
					WHERE media_id = ?';
                _sql(sql_filter($sql, 2, $media['media_id']));
            }
        }
        $sql = 'SELECT media_id
			FROM _bio_media
			WHERE media_type = ?
				AND media_mp3 = ?
			LIMIT 1';
        if ($v_next = _field(sql_filter($sql, 1, 0), 'media_id', 0)) {
            sleep(1);
            _redirect(_link($this->m(), array('v' => $v_next)));
        } else {
            $this->e('no_next');
        }
        return $this->e('.');
    }
Beispiel #15
0
 /**
  * Render flash in the form view
  *
  * @param   object  &$model   Element model
  * @param   object  &$params  Element params
  * @param   string  $file     Row data for this element
  *
  * @return  void
  */
 public function render(&$model, &$params, $file)
 {
     $fbConfig = JComponentHelper::getParams('com_fabrik');
     ini_set('display_errors', true);
     require_once COM_FABRIK_FRONTEND . '/libs/getid3/getid3/getid3.php';
     require_once COM_FABRIK_FRONTEND . '/libs/getid3/getid3/getid3.lib.php';
     getid3_lib::IncludeDependency(COM_FABRIK_FRONTEND . '/libs/getid3/getid3/extension.cache.mysql.php', __FILE__, true);
     $config = $this->config;
     $host = $config->get('host');
     $database = $config->get('db');
     $username = $config->get('user');
     $password = $config->get('password');
     $getID3 = new getID3_cached_mysql($host, $database, $username, $password);
     // Analyse file and store returned data in $ThisFileInfo
     $relPath = str_replace("\\", "/", JPATH_SITE . $file);
     $thisFileInfo = $getID3->analyze($relPath);
     $w = $params->get('fu_main_max_width', 0);
     $h = $params->get('fu_main_max_height', 0);
     if ($thisFileInfo && array_key_exists('swf', $thisFileInfo)) {
         if ($thisFileInfo['swf']['header']['frame_width'] < $w || $thisFileInfo['swf']['header']['frame_height'] < $h) {
             $w = $thisFileInfo['swf']['header']['frame_width'];
             $h = $thisFileInfo['swf']['header']['frame_height'];
         }
     }
     if ($w <= 0 || $h <= 0) {
         $w = 800;
         $h = 600;
     }
     $layout = $model->getLayout('flash');
     $displayData = new stdClass();
     $displayData->useThumbs = !$model->inDetailedView && $fbConfig->get('use_mediabox', true) && $params->get('make_thumbnail', false);
     $displayData->width = $w;
     $displayData->height = $h;
     $displayData->inDetailedView = $model->inDetailedView;
     $displayData->file = $file;
     if ($displayData->useThumbs) {
         // @TODO - work out how to do thumbnails
         $thumb_dir = $params->get('thumb_dir');
         if (!empty($thumb_dir)) {
             $file = str_replace("\\", "/", $file);
             $pathinfo = pathinfo($file);
             // $$$ hugh - apparently filename constant only added in PHP 5.2
             if (!isset($pathinfo['filename'])) {
                 $pathinfo['filename'] = explode('.', $pathinfo['basename']);
                 $pathinfo['filename'] = $pathinfo['filename'][0];
             }
             $thumb_path = COM_FABRIK_BASE . $thumb_dir . '/' . $pathinfo['filename'] . '.png';
             if (JFile::exists($thumb_path)) {
                 $thumb_file = COM_FABRIK_LIVESITE . $thumb_dir . '/' . $pathinfo['filename'] . '.png';
             } else {
                 $thumb_file = COM_FABRIK_LIVESITE . "media/com_fabrik/images/flash.jpg";
             }
         } else {
             $thumb_file = COM_FABRIK_LIVESITE . "media/com_fabrik/images/flash.jpg";
         }
         $file = str_replace("\\", "/", COM_FABRIK_LIVESITE . $file);
         $displayData->thumb = $thumb_file;
         $displayData->file = $file;
     }
     $this->output = $layout->render($displayData);
 }
Beispiel #16
0
 function WriteTags()
 {
     if (empty($this->filename)) {
         $this->errors[] = 'filename is undefined in getid3_writetags';
         return false;
     } elseif (!file_exists($this->filename)) {
         $this->errors[] = 'filename set to non-existant file "' . $this->filename . '" in getid3_writetags';
         return false;
     }
     if (!is_array($this->tagformats)) {
         $this->errors[] = 'tagformats must be an array in getid3_writetags';
         return false;
     }
     $TagFormatsToRemove = array();
     if (filesize($this->filename) == 0) {
         // empty file special case - allow any tag format, don't check existing format
         // could be useful if you want to generate tag data for a non-existant file
         $this->ThisFileInfo = array('fileformat' => '');
         $AllowedTagFormats = array('id3v1', 'id3v2.2', 'id3v2.3', 'id3v2.4', 'ape', 'lyrics3');
     } else {
         $getID3 = new getID3();
         $getID3->encoding = $this->tag_encoding;
         $this->ThisFileInfo = $getID3->analyze($this->filename);
         // check for what file types are allowed on this fileformat
         switch (@$this->ThisFileInfo['fileformat']) {
             case 'mp3':
             case 'mp2':
             case 'mp1':
                 $AllowedTagFormats = array('id3v1', 'id3v2.2', 'id3v2.3', 'id3v2.4', 'ape', 'lyrics3');
                 break;
             case 'mpc':
                 $AllowedTagFormats = array('ape');
                 break;
             case 'flac':
                 $AllowedTagFormats = array('metaflac');
                 break;
             case 'real':
                 $AllowedTagFormats = array('real');
                 break;
             case 'ogg':
                 switch (@$this->ThisFileInfo['audio']['dataformat']) {
                     case 'flac':
                         //$AllowedTagFormats = array('metaflac');
                         $this->errors[] = 'metaflac is not (yet) compatible with OggFLAC files';
                         return false;
                         break;
                     case 'vorbis':
                         $AllowedTagFormats = array('vorbiscomment');
                         break;
                     default:
                         $this->errors[] = 'metaflac is not (yet) compatible with Ogg files other than OggVorbis';
                         return false;
                         break;
                 }
                 break;
             default:
                 $AllowedTagFormats = array();
                 break;
         }
         foreach ($this->tagformats as $requested_tag_format) {
             if (!in_array($requested_tag_format, $AllowedTagFormats)) {
                 $errormessage = 'Tag format "' . $requested_tag_format . '" is not allowed on "' . @$this->ThisFileInfo['fileformat'];
                 if (@$this->ThisFileInfo['fileformat'] != @$this->ThisFileInfo['audio']['dataformat']) {
                     $errormessage .= '.' . @$this->ThisFileInfo['audio']['dataformat'];
                 }
                 $errormessage .= '" files';
                 $this->errors[] = $errormessage;
                 return false;
             }
         }
         // List of other tag formats, removed if requested
         if ($this->remove_other_tags) {
             foreach ($AllowedTagFormats as $AllowedTagFormat) {
                 switch ($AllowedTagFormat) {
                     case 'id3v2.2':
                     case 'id3v2.3':
                     case 'id3v2.4':
                         if (!in_array('id3v2', $TagFormatsToRemove) && !in_array('id3v2.2', $this->tagformats) && !in_array('id3v2.3', $this->tagformats) && !in_array('id3v2.4', $this->tagformats)) {
                             $TagFormatsToRemove[] = 'id3v2';
                         }
                         break;
                     default:
                         if (!in_array($AllowedTagFormat, $this->tagformats)) {
                             $TagFormatsToRemove[] = $AllowedTagFormat;
                         }
                         break;
                 }
             }
         }
     }
     $WritingFilesToInclude = array_merge($this->tagformats, $TagFormatsToRemove);
     // Check for required include files and include them
     foreach ($WritingFilesToInclude as $tagformat) {
         switch ($tagformat) {
             case 'ape':
                 $GETID3_ERRORARRAY =& $this->errors;
                 if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'write.apetag.php', __FILE__, false)) {
                     return false;
                 }
                 break;
             case 'id3v1':
             case 'lyrics3':
             case 'vorbiscomment':
             case 'metaflac':
             case 'real':
                 $GETID3_ERRORARRAY =& $this->errors;
                 if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'write.' . $tagformat . '.php', __FILE__, false)) {
                     return false;
                 }
                 break;
             case 'id3v2.2':
             case 'id3v2.3':
             case 'id3v2.4':
             case 'id3v2':
                 $GETID3_ERRORARRAY =& $this->errors;
                 if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'write.id3v2.php', __FILE__, false)) {
                     return false;
                 }
                 break;
             default:
                 $this->errors[] = 'unknown tag format "' . $tagformat . '" in $tagformats in WriteTags()';
                 return false;
                 break;
         }
     }
     // Validation of supplied data
     if (!is_array($this->tag_data)) {
         $this->errors[] = '$tag_data is not an array in WriteTags()';
         return false;
     }
     // convert supplied data array keys to upper case, if they're not already
     foreach ($this->tag_data as $tag_key => $tag_array) {
         if (strtoupper($tag_key) !== $tag_key) {
             $this->tag_data[strtoupper($tag_key)] = $this->tag_data[$tag_key];
             unset($this->tag_data[$tag_key]);
         }
     }
     // convert source data array keys to upper case, if they're not already
     if (!empty($this->ThisFileInfo['tags'])) {
         foreach ($this->ThisFileInfo['tags'] as $tag_format => $tag_data_array) {
             foreach ($tag_data_array as $tag_key => $tag_array) {
                 if (strtoupper($tag_key) !== $tag_key) {
                     $this->ThisFileInfo['tags'][$tag_format][strtoupper($tag_key)] = $this->ThisFileInfo['tags'][$tag_format][$tag_key];
                     unset($this->ThisFileInfo['tags'][$tag_format][$tag_key]);
                 }
             }
         }
     }
     // Convert "TRACK" to "TRACKNUMBER" (if needed) for compatability with all formats
     if (isset($this->tag_data['TRACK']) && !isset($this->tag_data['TRACKNUMBER'])) {
         $this->tag_data['TRACKNUMBER'] = $this->tag_data['TRACK'];
         unset($this->tag_data['TRACK']);
     }
     // Remove all other tag formats, if requested
     if ($this->remove_other_tags) {
         $this->DeleteTags($TagFormatsToRemove);
     }
     // Write data for each tag format
     foreach ($this->tagformats as $tagformat) {
         $success = false;
         // overridden if tag writing is successful
         switch ($tagformat) {
             case 'ape':
                 $ape_writer = new getid3_write_apetag();
                 if (($ape_writer->tag_data = $this->FormatDataForAPE()) !== false) {
                     $ape_writer->filename = $this->filename;
                     if (($success = $ape_writer->WriteAPEtag()) === false) {
                         $this->errors[] = 'WriteAPEtag() failed with message(s):<PRE><UL><LI>' . trim(implode('</LI><LI>', $ape_writer->errors)) . '</LI></UL></PRE>';
                     }
                 } else {
                     $this->errors[] = 'FormatDataForAPE() failed';
                 }
                 break;
             case 'id3v1':
                 $id3v1_writer = new getid3_write_id3v1();
                 if (($id3v1_writer->tag_data = $this->FormatDataForID3v1()) !== false) {
                     $id3v1_writer->filename = $this->filename;
                     if (($success = $id3v1_writer->WriteID3v1()) === false) {
                         $this->errors[] = 'WriteID3v1() failed with message(s):<PRE><UL><LI>' . trim(implode('</LI><LI>', $id3v1_writer->errors)) . '</LI></UL></PRE>';
                     }
                 } else {
                     $this->errors[] = 'FormatDataForID3v1() failed';
                 }
                 break;
             case 'id3v2.2':
             case 'id3v2.3':
             case 'id3v2.4':
                 $id3v2_writer = new getid3_write_id3v2();
                 $id3v2_writer->majorversion = intval(substr($tagformat, -1));
                 $id3v2_writer->paddedlength = $this->id3v2_paddedlength;
                 if (($id3v2_writer->tag_data = $this->FormatDataForID3v2($id3v2_writer->majorversion)) !== false) {
                     $id3v2_writer->filename = $this->filename;
                     if (($success = $id3v2_writer->WriteID3v2()) === false) {
                         $this->errors[] = 'WriteID3v2() failed with message(s):<PRE><UL><LI>' . trim(implode('</LI><LI>', $id3v2_writer->errors)) . '</LI></UL></PRE>';
                     }
                 } else {
                     $this->errors[] = 'FormatDataForID3v2() failed';
                 }
                 break;
             case 'vorbiscomment':
                 $vorbiscomment_writer = new getid3_write_vorbiscomment();
                 if (($vorbiscomment_writer->tag_data = $this->FormatDataForVorbisComment()) !== false) {
                     $vorbiscomment_writer->filename = $this->filename;
                     if (($success = $vorbiscomment_writer->WriteVorbisComment()) === false) {
                         $this->errors[] = 'WriteVorbisComment() failed with message(s):<PRE><UL><LI>' . trim(implode('</LI><LI>', $vorbiscomment_writer->errors)) . '</LI></UL></PRE>';
                     }
                 } else {
                     $this->errors[] = 'WriteVorbisComment() failed';
                 }
                 break;
             case 'metaflac':
                 $metaflac_writer = new getid3_write_metaflac();
                 if (($metaflac_writer->tag_data = $this->FormatDataForMetaFLAC()) !== false) {
                     $metaflac_writer->filename = $this->filename;
                     if (($success = $metaflac_writer->WriteMetaFLAC()) === false) {
                         $this->errors[] = 'WriteMetaFLAC() failed with message(s):<PRE><UL><LI>' . trim(implode('</LI><LI>', $metaflac_writer->errors)) . '</LI></UL></PRE>';
                     }
                 } else {
                     $this->errors[] = 'FormatDataForMetaFLAC() failed';
                 }
                 break;
             case 'real':
                 $real_writer = new getid3_write_real();
                 if (($real_writer->tag_data = $this->FormatDataForReal()) !== false) {
                     $real_writer->filename = $this->filename;
                     if (($success = $real_writer->WriteReal()) === false) {
                         $this->errors[] = 'WriteReal() failed with message(s):<PRE><UL><LI>' . trim(implode('</LI><LI>', $real_writer->errors)) . '</LI></UL></PRE>';
                     }
                 } else {
                     $this->errors[] = 'FormatDataForReal() failed';
                 }
                 break;
             default:
                 $this->errors[] = 'Invalid tag format to write: "' . $tagformat . '"';
                 return false;
                 break;
         }
         if (!$success) {
             return false;
         }
     }
     return true;
 }
<?php

/////////////////////////////////////////////////////////////////
/// getID3() by James Heinrich <*****@*****.**>               //
//  available at http://getid3.sourceforge.net                 //
//            or http://www.getid3.org                         //
/////////////////////////////////////////////////////////////////
//                                                             //
// /demo/demo.cache.dbm.php - part of getID3()                 //
// Sample script demonstrating the use of the DBM caching      //
// extension for getID3()                                      //
// See readme.txt for more details                             //
//                                                            ///
/////////////////////////////////////////////////////////////////
require_once '../getid3/getid3.php';
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'extension.cache.dbm.php', __FILE__, true);
$getID3 = new getID3_cached_dbm('db3', '/zimweb/test/test.dbm', '/zimweb/test/test.lock');
$r = $getID3->analyze('/path/to/files/filename.mp3');
echo '<pre>';
var_dump($r);
echo '</pre>';
// uncomment to clear cache
// $getID3->clear_cache();
Beispiel #18
0
// /demo/demo.write.php - part of getID3()                     //
// sample script for demonstrating writing ID3v1 and ID3v2     //
// tags for MP3, or Ogg comment tags for Ogg Vorbis            //
// See readme.txt for more details                             //
//                                                            ///
/////////////////////////////////////////////////////////////////
//die('Due to a security issue, this demo has been disabled. It can be enabled by removing line '.__LINE__.' in '.$_SERVER['PHP_SELF']);
$TaggingFormat = 'UTF-8';
header('Content-Type: text/html; charset=' . $TaggingFormat);
echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">';
echo '<html><head><title>getID3() - Sample tag writer</title></head><style type="text/css">BODY,TD,TH { font-family: sans-serif; font-size: 9pt;" }</style><body>';
require_once '../getid3/getid3.php';
// Initialize getID3 engine
$getID3 = new getID3();
$getID3->setOption(array('encoding' => $TaggingFormat));
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'write.php', __FILE__, true);
$browsescriptfilename = 'demo.browse.php';
$Filename = isset($_REQUEST['Filename']) ? $_REQUEST['Filename'] : '';
if (isset($_POST['WriteTags'])) {
    $TagFormatsToWrite = isset($_POST['TagFormatsToWrite']) ? $_POST['TagFormatsToWrite'] : array();
    if (!empty($TagFormatsToWrite)) {
        echo 'starting to write tag(s)<BR>';
        $tagwriter = new getid3_writetags();
        $tagwriter->filename = $Filename;
        $tagwriter->tagformats = $TagFormatsToWrite;
        $tagwriter->overwrite_tags = false;
        $tagwriter->tag_encoding = $TaggingFormat;
        if (!empty($_POST['remove_other_tags'])) {
            $tagwriter->remove_other_tags = true;
        }
        $commonkeysarray = array('Title', 'Artist', 'Album', 'Year', 'Comment');
 public function Analyze()
 {
     $info =& $this->getid3->info;
     // http://www.volweb.cz/str/tags.htm
     if (!getid3_lib::intValueSupported($info['filesize'])) {
         $info['warning'][] = 'Unable to check for Lyrics3 because file is larger than ' . round(PHP_INT_MAX / 1073741824) . 'GB';
         return false;
     }
     $this->fseek(0 - 128 - 9 - 6, SEEK_END);
     // end - ID3v1 - "LYRICSEND" - [Lyrics3size]
     $lyrics3_id3v1 = $this->fread(128 + 9 + 6);
     $lyrics3lsz = substr($lyrics3_id3v1, 0, 6);
     // Lyrics3size
     $lyrics3end = substr($lyrics3_id3v1, 6, 9);
     // LYRICSEND or LYRICS200
     $id3v1tag = substr($lyrics3_id3v1, 15, 128);
     // ID3v1
     if ($lyrics3end == 'LYRICSEND') {
         // Lyrics3v1, ID3v1, no APE
         $lyrics3size = 5100;
         $lyrics3offset = $info['filesize'] - 128 - $lyrics3size;
         $lyrics3version = 1;
     } elseif ($lyrics3end == 'LYRICS200') {
         // Lyrics3v2, ID3v1, no APE
         // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200'
         $lyrics3size = $lyrics3lsz + 6 + strlen('LYRICS200');
         $lyrics3offset = $info['filesize'] - 128 - $lyrics3size;
         $lyrics3version = 2;
     } elseif (substr(strrev($lyrics3_id3v1), 0, 9) == strrev('LYRICSEND')) {
         // Lyrics3v1, no ID3v1, no APE
         $lyrics3size = 5100;
         $lyrics3offset = $info['filesize'] - $lyrics3size;
         $lyrics3version = 1;
         $lyrics3offset = $info['filesize'] - $lyrics3size;
     } elseif (substr(strrev($lyrics3_id3v1), 0, 9) == strrev('LYRICS200')) {
         // Lyrics3v2, no ID3v1, no APE
         $lyrics3size = strrev(substr(strrev($lyrics3_id3v1), 9, 6)) + 6 + strlen('LYRICS200');
         // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200'
         $lyrics3offset = $info['filesize'] - $lyrics3size;
         $lyrics3version = 2;
     } else {
         if (isset($info['ape']['tag_offset_start']) && $info['ape']['tag_offset_start'] > 15) {
             $this->fseek($info['ape']['tag_offset_start'] - 15);
             $lyrics3lsz = $this->fread(6);
             $lyrics3end = $this->fread(9);
             if ($lyrics3end == 'LYRICSEND') {
                 // Lyrics3v1, APE, maybe ID3v1
                 $lyrics3size = 5100;
                 $lyrics3offset = $info['ape']['tag_offset_start'] - $lyrics3size;
                 $info['avdataend'] = $lyrics3offset;
                 $lyrics3version = 1;
                 $info['warning'][] = 'APE tag located after Lyrics3, will probably break Lyrics3 compatability';
             } elseif ($lyrics3end == 'LYRICS200') {
                 // Lyrics3v2, APE, maybe ID3v1
                 $lyrics3size = $lyrics3lsz + 6 + strlen('LYRICS200');
                 // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200'
                 $lyrics3offset = $info['ape']['tag_offset_start'] - $lyrics3size;
                 $lyrics3version = 2;
                 $info['warning'][] = 'APE tag located after Lyrics3, will probably break Lyrics3 compatability';
             }
         }
     }
     if (isset($lyrics3offset)) {
         $info['avdataend'] = $lyrics3offset;
         $this->getLyrics3Data($lyrics3offset, $lyrics3version, $lyrics3size);
         if (!isset($info['ape'])) {
             $GETID3_ERRORARRAY =& $info['warning'];
             getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.tag.apetag.php', __FILE__, true);
             $getid3_temp = new getID3();
             $getid3_temp->openfile($this->getid3->filename);
             $getid3_apetag = new getid3_apetag($getid3_temp);
             $getid3_apetag->overrideendoffset = $info['lyrics3']['tag_offset_start'];
             $getid3_apetag->Analyze();
             if (!empty($getid3_temp->info['ape'])) {
                 $info['ape'] = $getid3_temp->info['ape'];
             }
             if (!empty($getid3_temp->info['replay_gain'])) {
                 $info['replay_gain'] = $getid3_temp->info['replay_gain'];
             }
             unset($getid3_temp, $getid3_apetag);
         }
     }
     return true;
 }
 public function Analyze()
 {
     $info =& $this->getid3->info;
     $info['fileformat'] = 'jpg';
     $info['video']['dataformat'] = 'jpg';
     $info['video']['lossless'] = false;
     $info['video']['bits_per_sample'] = 24;
     $info['video']['pixel_aspect_ratio'] = (double) 1;
     fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);
     $imageinfo = array();
     //list($width, $height, $type) = getid3_lib::GetDataImageSize(fread($this->getid3->fp, $info['filesize']), $imageinfo);
     list($width, $height, $type) = getimagesize($info['filenamepath'], $imageinfo);
     // http://www.getid3.org/phpBB3/viewtopic.php?t=1474
     if (isset($imageinfo['APP13'])) {
         // http://php.net/iptcparse
         // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/IPTC.html
         $iptc_parsed = iptcparse($imageinfo['APP13']);
         if (is_array($iptc_parsed)) {
             foreach ($iptc_parsed as $iptc_key_raw => $iptc_values) {
                 list($iptc_record, $iptc_tagkey) = explode('#', $iptc_key_raw);
                 $iptc_tagkey = intval(ltrim($iptc_tagkey, '0'));
                 foreach ($iptc_values as $key => $value) {
                     $IPTCrecordName = $this->IPTCrecordName($iptc_record);
                     $IPTCrecordTagName = $this->IPTCrecordTagName($iptc_record, $iptc_tagkey);
                     if (isset($info['iptc'][$IPTCrecordName][$IPTCrecordTagName])) {
                         $info['iptc'][$IPTCrecordName][$IPTCrecordTagName][] = $value;
                     } else {
                         $info['iptc'][$IPTCrecordName][$IPTCrecordTagName] = array($value);
                     }
                 }
             }
         }
     }
     $returnOK = false;
     switch ($type) {
         case IMG_JPG:
             $info['video']['resolution_x'] = $width;
             $info['video']['resolution_y'] = $height;
             if (isset($imageinfo['APP1'])) {
                 if (function_exists('exif_read_data')) {
                     if (substr($imageinfo['APP1'], 0, 4) == 'Exif') {
                         //$info['warning'][] = 'known issue: https://bugs.php.net/bug.php?id=62523';
                         //return false;
                         $info['jpg']['exif'] = @exif_read_data($info['filenamepath'], null, true, false);
                     } else {
                         $info['warning'][] = 'exif_read_data() cannot parse non-EXIF data in APP1 (expected "Exif", found "' . substr($imageinfo['APP1'], 0, 4) . '")';
                     }
                 } else {
                     $info['warning'][] = 'EXIF parsing only available when ' . (GETID3_OS_ISWINDOWS ? 'php_exif.dll enabled' : 'compiled with --enable-exif');
                 }
             }
             $returnOK = true;
             break;
         default:
             break;
     }
     $cast_as_appropriate_keys = array('EXIF', 'IFD0', 'THUMBNAIL');
     foreach ($cast_as_appropriate_keys as $exif_key) {
         if (isset($info['jpg']['exif'][$exif_key])) {
             foreach ($info['jpg']['exif'][$exif_key] as $key => $value) {
                 $info['jpg']['exif'][$exif_key][$key] = $this->CastAsAppropriate($value);
             }
         }
     }
     if (isset($info['jpg']['exif']['GPS'])) {
         if (isset($info['jpg']['exif']['GPS']['GPSVersion'])) {
             for ($i = 0; $i < 4; $i++) {
                 $version_subparts[$i] = ord(substr($info['jpg']['exif']['GPS']['GPSVersion'], $i, 1));
             }
             $info['jpg']['exif']['GPS']['computed']['version'] = 'v' . implode('.', $version_subparts);
         }
         if (isset($info['jpg']['exif']['GPS']['GPSDateStamp'])) {
             $explodedGPSDateStamp = explode(':', $info['jpg']['exif']['GPS']['GPSDateStamp']);
             $computed_time[5] = isset($explodedGPSDateStamp[0]) ? $explodedGPSDateStamp[0] : '';
             $computed_time[3] = isset($explodedGPSDateStamp[1]) ? $explodedGPSDateStamp[1] : '';
             $computed_time[4] = isset($explodedGPSDateStamp[2]) ? $explodedGPSDateStamp[2] : '';
             if (function_exists('date_default_timezone_set')) {
                 date_default_timezone_set('UTC');
             } else {
                 ini_set('date.timezone', 'UTC');
             }
             $computed_time = array(0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0);
             if (isset($info['jpg']['exif']['GPS']['GPSTimeStamp']) && is_array($info['jpg']['exif']['GPS']['GPSTimeStamp'])) {
                 foreach ($info['jpg']['exif']['GPS']['GPSTimeStamp'] as $key => $value) {
                     $computed_time[$key] = getid3_lib::DecimalizeFraction($value);
                 }
             }
             $info['jpg']['exif']['GPS']['computed']['timestamp'] = mktime($computed_time[0], $computed_time[1], $computed_time[2], $computed_time[3], $computed_time[4], $computed_time[5]);
         }
         if (isset($info['jpg']['exif']['GPS']['GPSLatitude']) && is_array($info['jpg']['exif']['GPS']['GPSLatitude'])) {
             $direction_multiplier = isset($info['jpg']['exif']['GPS']['GPSLatitudeRef']) && $info['jpg']['exif']['GPS']['GPSLatitudeRef'] == 'S' ? -1 : 1;
             foreach ($info['jpg']['exif']['GPS']['GPSLatitude'] as $key => $value) {
                 $computed_latitude[$key] = getid3_lib::DecimalizeFraction($value);
             }
             $info['jpg']['exif']['GPS']['computed']['latitude'] = $direction_multiplier * ($computed_latitude[0] + $computed_latitude[1] / 60 + $computed_latitude[2] / 3600);
         }
         if (isset($info['jpg']['exif']['GPS']['GPSLongitude']) && is_array($info['jpg']['exif']['GPS']['GPSLongitude'])) {
             $direction_multiplier = isset($info['jpg']['exif']['GPS']['GPSLongitudeRef']) && $info['jpg']['exif']['GPS']['GPSLongitudeRef'] == 'W' ? -1 : 1;
             foreach ($info['jpg']['exif']['GPS']['GPSLongitude'] as $key => $value) {
                 $computed_longitude[$key] = getid3_lib::DecimalizeFraction($value);
             }
             $info['jpg']['exif']['GPS']['computed']['longitude'] = $direction_multiplier * ($computed_longitude[0] + $computed_longitude[1] / 60 + $computed_longitude[2] / 3600);
         }
         if (isset($info['jpg']['exif']['GPS']['GPSAltitudeRef'])) {
             $info['jpg']['exif']['GPS']['GPSAltitudeRef'] = ord($info['jpg']['exif']['GPS']['GPSAltitudeRef']);
             // 0 = above sea level; 1 = below sea level
         }
         if (isset($info['jpg']['exif']['GPS']['GPSAltitude'])) {
             $direction_multiplier = !empty($info['jpg']['exif']['GPS']['GPSAltitudeRef']) ? -1 : 1;
             // 0 = above sea level; 1 = below sea level
             $info['jpg']['exif']['GPS']['computed']['altitude'] = $direction_multiplier * getid3_lib::DecimalizeFraction($info['jpg']['exif']['GPS']['GPSAltitude']);
         }
     }
     if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.tag.xmp.php', __FILE__, false)) {
         if (isset($info['filenamepath'])) {
             $image_xmp = new Image_XMP($info['filenamepath']);
             $xmp_raw = $image_xmp->getAllTags();
             foreach ($xmp_raw as $key => $value) {
                 if (strpos($key, ':')) {
                     list($subsection, $tagname) = explode(':', $key);
                     $info['xmp'][$subsection][$tagname] = $this->CastAsAppropriate($value);
                 } else {
                     $info['warning'][] = 'XMP: expecting "<subsection>:<tagname>", found "' . $key . '"';
                 }
             }
         }
     }
     if (!$returnOK) {
         unset($info['fileformat']);
         return false;
     }
     return true;
 }
 function ParseRIFF(&$fd, $startoffset, $maxoffset, &$ThisFileInfo)
 {
     $maxoffset = min($maxoffset, $ThisFileInfo['avdataend']);
     $RIFFchunk = false;
     fseek($fd, $startoffset, SEEK_SET);
     while (ftell($fd) < $maxoffset) {
         $chunkname = fread($fd, 4);
         if (strlen($chunkname) < 4) {
             $ThisFileInfo['error'][] = 'Expecting chunk name at offset ' . (ftell($fd) - 4) . ' but found nothing. Aborting RIFF parsing.';
             break;
         }
         $chunksize = getid3_riff::EitherEndian2Int($ThisFileInfo, fread($fd, 4));
         if ($chunksize == 0) {
             $ThisFileInfo['error'][] = 'Chunk size at offset ' . (ftell($fd) - 4) . ' is zero. Aborting RIFF parsing.';
             break;
         }
         if ($chunksize % 2 != 0) {
             // all structures are packed on word boundaries
             $chunksize++;
         }
         switch ($chunkname) {
             case 'LIST':
                 $listname = fread($fd, 4);
                 switch ($listname) {
                     case 'movi':
                     case 'rec ':
                         $RIFFchunk[$listname]['offset'] = ftell($fd) - 4;
                         $RIFFchunk[$listname]['size'] = $chunksize;
                         static $ParsedAudioStream = false;
                         if ($ParsedAudioStream) {
                             // skip over
                         } else {
                             $WhereWeWere = ftell($fd);
                             $AudioChunkHeader = fread($fd, 12);
                             $AudioChunkStreamNum = substr($AudioChunkHeader, 0, 2);
                             $AudioChunkStreamType = substr($AudioChunkHeader, 2, 2);
                             $AudioChunkSize = getid3_lib::LittleEndian2Int(substr($AudioChunkHeader, 4, 4));
                             if ($AudioChunkStreamType == 'wb') {
                                 $FirstFourBytes = substr($AudioChunkHeader, 8, 4);
                                 if (preg_match('/^\\xFF[\\xE2-\\xE7\\xF2-\\xF7\\xFA-\\xFF][\\x00-\\xEB]/s', $FirstFourBytes)) {
                                     // MP3
                                     if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) {
                                         $dummy = $ThisFileInfo;
                                         $dummy['avdataoffset'] = ftell($fd) - 4;
                                         $dummy['avdataend'] = ftell($fd) + $AudioChunkSize;
                                         getid3_mp3::getOnlyMPEGaudioInfo($fd, $dummy, $dummy['avdataoffset'], false);
                                         if (isset($dummy['mpeg']['audio'])) {
                                             $ThisFileInfo = $dummy;
                                             $ThisFileInfo['audio']['dataformat'] = 'mp' . $ThisFileInfo['mpeg']['audio']['layer'];
                                             $ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['mpeg']['audio']['sample_rate'];
                                             $ThisFileInfo['audio']['channels'] = $ThisFileInfo['mpeg']['audio']['channels'];
                                             $ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['mpeg']['audio']['bitrate'];
                                             $ThisFileInfo['bitrate'] = $ThisFileInfo['audio']['bitrate'];
                                             $ThisFileInfo['audio']['bitrate_mode'] = strtolower($ThisFileInfo['mpeg']['audio']['bitrate_mode']);
                                         }
                                     }
                                 } elseif (preg_match('/^\\x0B\\x77/s', $FirstFourBytes)) {
                                     // AC3
                                     $GETID3_ERRORARRAY =& $ThisFileInfo['warning'];
                                     if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.ac3.php', __FILE__, false)) {
                                         $dummy = $ThisFileInfo;
                                         $dummy['avdataoffset'] = ftell($fd) - 4;
                                         $dummy['avdataend'] = ftell($fd) + $AudioChunkSize;
                                         $dummy['error'] = array();
                                         $ac3_tag = new getid3_ac3($fd, $dummy);
                                         if (empty($dummy['error'])) {
                                             $ThisFileInfo['audio'] = $dummy['audio'];
                                             $ThisFileInfo['ac3'] = $dummy['ac3'];
                                             $ThisFileInfo['warning'] = $dummy['warning'];
                                         }
                                     }
                                 }
                             }
                             $ParsedAudioStream = true;
                             fseek($fd, $WhereWeWere, SEEK_SET);
                         }
                         fseek($fd, $chunksize - 4, SEEK_CUR);
                         break;
                     default:
                         if (!isset($RIFFchunk[$listname])) {
                             $RIFFchunk[$listname] = array();
                         }
                         $LISTchunkParent = $listname;
                         $LISTchunkMaxOffset = ftell($fd) - 4 + $chunksize;
                         if ($parsedChunk = getid3_riff::ParseRIFF($fd, ftell($fd), ftell($fd) + $chunksize - 4, $ThisFileInfo)) {
                             $RIFFchunk[$listname] = array_merge_recursive($RIFFchunk[$listname], $parsedChunk);
                         }
                         break;
                 }
                 break;
             default:
                 $thisindex = 0;
                 if (isset($RIFFchunk[$chunkname]) && is_array($RIFFchunk[$chunkname])) {
                     $thisindex = count($RIFFchunk[$chunkname]);
                 }
                 $RIFFchunk[$chunkname][$thisindex]['offset'] = ftell($fd) - 8;
                 $RIFFchunk[$chunkname][$thisindex]['size'] = $chunksize;
                 switch ($chunkname) {
                     case 'data':
                         $ThisFileInfo['avdataoffset'] = ftell($fd);
                         $ThisFileInfo['avdataend'] = $ThisFileInfo['avdataoffset'] + $chunksize;
                         $RIFFdataChunkContentsTest = fread($fd, 36);
                         if (strlen($RIFFdataChunkContentsTest) > 0 && preg_match('/^\\xFF[\\xE2-\\xE7\\xF2-\\xF7\\xFA-\\xFF][\\x00-\\xEB]/s', substr($RIFFdataChunkContentsTest, 0, 4))) {
                             // Probably is MP3 data
                             if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($RIFFdataChunkContentsTest, 0, 4))) {
                                 getid3_mp3::getOnlyMPEGaudioInfo($fd, $ThisFileInfo, $RIFFchunk[$chunkname][$thisindex]['offset'], false);
                             }
                         } elseif (strlen($RIFFdataChunkContentsTest) > 0 && substr($RIFFdataChunkContentsTest, 0, 2) == "\vw") {
                             // This is probably AC-3 data
                             $GETID3_ERRORARRAY =& $ThisFileInfo['warning'];
                             if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.ac3.php', __FILE__, false)) {
                                 $dummy = $ThisFileInfo;
                                 $dummy['avdataoffset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
                                 $dummy['avdataend'] = $dummy['avdataoffset'] + $RIFFchunk[$chunkname][$thisindex]['size'];
                                 $dummy['error'] = array();
                                 $ac3_tag = new getid3_ac3($fd, $dummy);
                                 if (empty($dummy['error'])) {
                                     $ThisFileInfo['audio'] = $dummy['audio'];
                                     $ThisFileInfo['ac3'] = $dummy['ac3'];
                                     $ThisFileInfo['warning'] = $dummy['warning'];
                                 }
                             }
                         } elseif (strlen($RIFFdataChunkContentsTest) > 0 && substr($RIFFdataChunkContentsTest, 8, 2) == "w\v") {
                             // Dolby Digital WAV
                             // AC-3 content, but not encoded in same format as normal AC-3 file
                             // For one thing, byte order is swapped
                             $GETID3_ERRORARRAY =& $ThisFileInfo['warning'];
                             if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.ac3.php', __FILE__, false)) {
                                 // ok to use tmpfile here - only 56 bytes
                                 if ($fd_temp = tmpfile()) {
                                     for ($i = 0; $i < 28; $i += 2) {
                                         // swap byte order
                                         fwrite($fd_temp, substr($RIFFdataChunkContentsTest, 8 + $i + 1, 1));
                                         fwrite($fd_temp, substr($RIFFdataChunkContentsTest, 8 + $i + 0, 1));
                                     }
                                     $dummy = $ThisFileInfo;
                                     $dummy['avdataoffset'] = 0;
                                     $dummy['avdataend'] = 20;
                                     $dummy['error'] = array();
                                     $ac3_tag = new getid3_ac3($fd_temp, $dummy);
                                     fclose($fd_temp);
                                     if (empty($dummy['error'])) {
                                         $ThisFileInfo['audio'] = $dummy['audio'];
                                         $ThisFileInfo['ac3'] = $dummy['ac3'];
                                         $ThisFileInfo['warning'] = $dummy['warning'];
                                     } else {
                                         $ThisFileInfo['error'][] = 'Errors parsing DolbyDigital WAV: ' . explode(';', $dummy['error']);
                                     }
                                 } else {
                                     $ThisFileInfo['error'][] = 'Could not create temporary file to analyze DolbyDigital WAV';
                                 }
                             }
                         } elseif (strlen($RIFFdataChunkContentsTest) > 0 && substr($RIFFdataChunkContentsTest, 0, 4) == 'wvpk') {
                             // This is WavPack data
                             $ThisFileInfo['wavpack']['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
                             $ThisFileInfo['wavpack']['size'] = getid3_lib::LittleEndian2Int(substr($RIFFdataChunkContentsTest, 4, 4));
                             getid3_riff::RIFFparseWavPackHeader(substr($RIFFdataChunkContentsTest, 8, 28), $ThisFileInfo);
                         } else {
                             // This is some other kind of data (quite possibly just PCM)
                             // do nothing special, just skip it
                         }
                         fseek($fd, $RIFFchunk[$chunkname][$thisindex]['offset'] + 8 + $chunksize, SEEK_SET);
                         break;
                     case 'bext':
                     case 'cart':
                     case 'fmt ':
                     case 'MEXT':
                     case 'DISP':
                         // always read data in
                         $RIFFchunk[$chunkname][$thisindex]['data'] = fread($fd, $chunksize);
                         break;
                     default:
                         if (!empty($LISTchunkParent) && $RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size'] <= $LISTchunkMaxOffset) {
                             $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
                             $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size'] = $RIFFchunk[$chunkname][$thisindex]['size'];
                             unset($RIFFchunk[$chunkname][$thisindex]['offset']);
                             unset($RIFFchunk[$chunkname][$thisindex]['size']);
                             if (isset($RIFFchunk[$chunkname][$thisindex]) && empty($RIFFchunk[$chunkname][$thisindex])) {
                                 unset($RIFFchunk[$chunkname][$thisindex]);
                             }
                             if (isset($RIFFchunk[$chunkname]) && empty($RIFFchunk[$chunkname])) {
                                 unset($RIFFchunk[$chunkname]);
                             }
                             $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['data'] = fread($fd, $chunksize);
                         } elseif ($chunksize < 2048) {
                             // only read data in if smaller than 2kB
                             $RIFFchunk[$chunkname][$thisindex]['data'] = fread($fd, $chunksize);
                         } else {
                             fseek($fd, $chunksize, SEEK_CUR);
                         }
                         break;
                 }
                 break;
         }
     }
     return $RIFFchunk;
 }
<?php

/////////////////////////////////////////////////////////////////
/// getID3() by James Heinrich <*****@*****.**>               //
//  available at http://getid3.sourceforge.net                 //
//            or http://www.getid3.org                         //
/////////////////////////////////////////////////////////////////
// See readme.txt for more details                             //
/////////////////////////////////////////////////////////////////
//                                                             //
// module.audio-video.asf.php                                  //
// module for analyzing ASF, WMA and WMV files                 //
// dependencies: module.audio-video.riff.php                   //
//                                                            ///
/////////////////////////////////////////////////////////////////
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio-video.riff.php', __FILE__, true);
$GUIDarray = getid3_asf::KnownGUIDs();
foreach ($GUIDarray as $GUIDname => $hexstringvalue) {
    // initialize all GUID constants
    define($GUIDname, getid3_asf::GUIDtoBytestring($hexstringvalue));
}
class getid3_asf
{
    function getid3_asf(&$fd, &$ThisFileInfo)
    {
        // Shortcuts
        $thisfile_audio =& $ThisFileInfo['audio'];
        $thisfile_video =& $ThisFileInfo['video'];
        $ThisFileInfo['asf'] = array();
        $thisfile_asf =& $ThisFileInfo['asf'];
        $thisfile_asf['comments'] = array();
 public function Analyze()
 {
     $info =& $this->getid3->info;
     // initialize these values to an empty array, otherwise they default to NULL
     // and you can't append array values to a NULL value
     $info['riff'] = array('raw' => array());
     // Shortcuts
     $thisfile_riff =& $info['riff'];
     $thisfile_riff_raw =& $thisfile_riff['raw'];
     $thisfile_audio =& $info['audio'];
     $thisfile_video =& $info['video'];
     $thisfile_audio_dataformat =& $thisfile_audio['dataformat'];
     $thisfile_riff_audio =& $thisfile_riff['audio'];
     $thisfile_riff_video =& $thisfile_riff['video'];
     $Original['avdataoffset'] = $info['avdataoffset'];
     $Original['avdataend'] = $info['avdataend'];
     $this->fseek($info['avdataoffset']);
     $RIFFheader = $this->fread(12);
     $offset = $this->ftell();
     $RIFFtype = substr($RIFFheader, 0, 4);
     $RIFFsize = substr($RIFFheader, 4, 4);
     $RIFFsubtype = substr($RIFFheader, 8, 4);
     switch ($RIFFtype) {
         case 'FORM':
             // AIFF, AIFC
             //$info['fileformat']   = 'aiff';
             $this->container = 'aiff';
             $thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize);
             $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, $offset + $thisfile_riff['header_size'] - 4);
             break;
         case 'RIFF':
             // AVI, WAV, etc
         // AVI, WAV, etc
         case 'SDSS':
             // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com)
         // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com)
         case 'RMP3':
             // RMP3 is identical to RIFF, just renamed. Used by [unknown program] when creating RIFF-MP3s
             //$info['fileformat']   = 'riff';
             $this->container = 'riff';
             $thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize);
             if ($RIFFsubtype == 'RMP3') {
                 // RMP3 is identical to WAVE, just renamed. Used by [unknown program] when creating RIFF-MP3s
                 $RIFFsubtype = 'WAVE';
             }
             if ($RIFFsubtype != 'AMV ') {
                 // AMV files are RIFF-AVI files with parts of the spec deliberately broken, such as chunk size fields hardcoded to zero (because players known in hardware that these fields are always a certain size
                 // Handled separately in ParseRIFFAMV()
                 $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, $offset + $thisfile_riff['header_size'] - 4);
             }
             if ($info['avdataend'] - $info['filesize'] == 1) {
                 // LiteWave appears to incorrectly *not* pad actual output file
                 // to nearest WORD boundary so may appear to be short by one
                 // byte, in which case - skip warning
                 $info['avdataend'] = $info['filesize'];
             }
             $nextRIFFoffset = $Original['avdataoffset'] + 8 + $thisfile_riff['header_size'];
             // 8 = "RIFF" + 32-bit offset
             while ($nextRIFFoffset < min($info['filesize'], $info['avdataend'])) {
                 try {
                     $this->fseek($nextRIFFoffset);
                 } catch (getid3_exception $e) {
                     if ($e->getCode() == 10) {
                         //$this->warning('RIFF parser: '.$e->getMessage());
                         $this->error('AVI extends beyond ' . round(PHP_INT_MAX / 1073741824) . 'GB and PHP filesystem functions cannot read that far, playtime may be wrong');
                         $this->warning('[avdataend] value may be incorrect, multiple AVIX chunks may be present');
                         break;
                     } else {
                         throw $e;
                     }
                 }
                 $nextRIFFheader = $this->fread(12);
                 if ($nextRIFFoffset == $info['avdataend'] - 1) {
                     if (substr($nextRIFFheader, 0, 1) == "") {
                         // RIFF padded to WORD boundary, we're actually already at the end
                         break;
                     }
                 }
                 $nextRIFFheaderID = substr($nextRIFFheader, 0, 4);
                 $nextRIFFsize = $this->EitherEndian2Int(substr($nextRIFFheader, 4, 4));
                 $nextRIFFtype = substr($nextRIFFheader, 8, 4);
                 $chunkdata = array();
                 $chunkdata['offset'] = $nextRIFFoffset + 8;
                 $chunkdata['size'] = $nextRIFFsize;
                 $nextRIFFoffset = $chunkdata['offset'] + $chunkdata['size'];
                 switch ($nextRIFFheaderID) {
                     case 'RIFF':
                         $chunkdata['chunks'] = $this->ParseRIFF($chunkdata['offset'] + 4, $nextRIFFoffset);
                         if (!isset($thisfile_riff[$nextRIFFtype])) {
                             $thisfile_riff[$nextRIFFtype] = array();
                         }
                         $thisfile_riff[$nextRIFFtype][] = $chunkdata;
                         break;
                     case 'AMV ':
                         unset($info['riff']);
                         $info['amv'] = $this->ParseRIFFAMV($chunkdata['offset'] + 4, $nextRIFFoffset);
                         break;
                     case 'JUNK':
                         // ignore
                         $thisfile_riff[$nextRIFFheaderID][] = $chunkdata;
                         break;
                     case 'IDVX':
                         $info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunkdata['size']));
                         break;
                     default:
                         if ($info['filesize'] == $chunkdata['offset'] - 8 + 128) {
                             $DIVXTAG = $nextRIFFheader . $this->fread(128 - 12);
                             if (substr($DIVXTAG, -7) == 'DIVXTAG') {
                                 // DIVXTAG is supposed to be inside an IDVX chunk in a LIST chunk, but some bad encoders just slap it on the end of a file
                                 $this->warning('Found wrongly-structured DIVXTAG at offset ' . ($this->ftell() - 128) . ', parsing anyway');
                                 $info['divxtag']['comments'] = self::ParseDIVXTAG($DIVXTAG);
                                 break 2;
                             }
                         }
                         $this->warning('Expecting "RIFF|JUNK|IDVX" at ' . $nextRIFFoffset . ', found "' . $nextRIFFheaderID . '" (' . getid3_lib::PrintHexBytes($nextRIFFheaderID) . ') - skipping rest of file');
                         break 2;
                 }
             }
             if ($RIFFsubtype == 'WAVE') {
                 $thisfile_riff_WAVE =& $thisfile_riff['WAVE'];
             }
             break;
         default:
             $this->error('Cannot parse RIFF (this is maybe not a RIFF / WAV / AVI file?) - expecting "FORM|RIFF|SDSS|RMP3" found "' . $RIFFsubtype . '" instead');
             //unset($info['fileformat']);
             return false;
     }
     $streamindex = 0;
     switch ($RIFFsubtype) {
         // http://en.wikipedia.org/wiki/Wav
         case 'WAVE':
             $info['fileformat'] = 'wav';
             if (empty($thisfile_audio['bitrate_mode'])) {
                 $thisfile_audio['bitrate_mode'] = 'cbr';
             }
             if (empty($thisfile_audio_dataformat)) {
                 $thisfile_audio_dataformat = 'wav';
             }
             if (isset($thisfile_riff_WAVE['data'][0]['offset'])) {
                 $info['avdataoffset'] = $thisfile_riff_WAVE['data'][0]['offset'] + 8;
                 $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff_WAVE['data'][0]['size'];
             }
             if (isset($thisfile_riff_WAVE['fmt '][0]['data'])) {
                 $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($thisfile_riff_WAVE['fmt '][0]['data']);
                 $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
                 if (!isset($thisfile_riff_audio[$streamindex]['bitrate']) || $thisfile_riff_audio[$streamindex]['bitrate'] == 0) {
                     $info['error'][] = 'Corrupt RIFF file: bitrate_audio == zero';
                     return false;
                 }
                 $thisfile_riff_raw['fmt '] = $thisfile_riff_audio[$streamindex]['raw'];
                 unset($thisfile_riff_audio[$streamindex]['raw']);
                 $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
                 $thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
                 if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') {
                     $info['warning'][] = 'Audio codec = ' . $thisfile_audio['codec'];
                 }
                 $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
                 if (empty($info['playtime_seconds'])) {
                     // may already be set (e.g. DTS-WAV)
                     $info['playtime_seconds'] = (double) (($info['avdataend'] - $info['avdataoffset']) * 8 / $thisfile_audio['bitrate']);
                 }
                 $thisfile_audio['lossless'] = false;
                 if (isset($thisfile_riff_WAVE['data'][0]['offset']) && isset($thisfile_riff_raw['fmt ']['wFormatTag'])) {
                     switch ($thisfile_riff_raw['fmt ']['wFormatTag']) {
                         case 0x1:
                             // PCM
                             $thisfile_audio['lossless'] = true;
                             break;
                         case 0x2000:
                             // AC-3
                             $thisfile_audio_dataformat = 'ac3';
                             break;
                         default:
                             // do nothing
                             break;
                     }
                 }
                 $thisfile_audio['streams'][$streamindex]['wformattag'] = $thisfile_audio['wformattag'];
                 $thisfile_audio['streams'][$streamindex]['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
                 $thisfile_audio['streams'][$streamindex]['lossless'] = $thisfile_audio['lossless'];
                 $thisfile_audio['streams'][$streamindex]['dataformat'] = $thisfile_audio_dataformat;
             }
             if (isset($thisfile_riff_WAVE['rgad'][0]['data'])) {
                 // shortcuts
                 $rgadData =& $thisfile_riff_WAVE['rgad'][0]['data'];
                 $thisfile_riff_raw['rgad'] = array('track' => array(), 'album' => array());
                 $thisfile_riff_raw_rgad =& $thisfile_riff_raw['rgad'];
                 $thisfile_riff_raw_rgad_track =& $thisfile_riff_raw_rgad['track'];
                 $thisfile_riff_raw_rgad_album =& $thisfile_riff_raw_rgad['album'];
                 $thisfile_riff_raw_rgad['fPeakAmplitude'] = getid3_lib::LittleEndian2Float(substr($rgadData, 0, 4));
                 $thisfile_riff_raw_rgad['nRadioRgAdjust'] = $this->EitherEndian2Int(substr($rgadData, 4, 2));
                 $thisfile_riff_raw_rgad['nAudiophileRgAdjust'] = $this->EitherEndian2Int(substr($rgadData, 6, 2));
                 $nRadioRgAdjustBitstring = str_pad(getid3_lib::Dec2Bin($thisfile_riff_raw_rgad['nRadioRgAdjust']), 16, '0', STR_PAD_LEFT);
                 $nAudiophileRgAdjustBitstring = str_pad(getid3_lib::Dec2Bin($thisfile_riff_raw_rgad['nAudiophileRgAdjust']), 16, '0', STR_PAD_LEFT);
                 $thisfile_riff_raw_rgad_track['name'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 0, 3));
                 $thisfile_riff_raw_rgad_track['originator'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 3, 3));
                 $thisfile_riff_raw_rgad_track['signbit'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 6, 1));
                 $thisfile_riff_raw_rgad_track['adjustment'] = getid3_lib::Bin2Dec(substr($nRadioRgAdjustBitstring, 7, 9));
                 $thisfile_riff_raw_rgad_album['name'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 0, 3));
                 $thisfile_riff_raw_rgad_album['originator'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 3, 3));
                 $thisfile_riff_raw_rgad_album['signbit'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 6, 1));
                 $thisfile_riff_raw_rgad_album['adjustment'] = getid3_lib::Bin2Dec(substr($nAudiophileRgAdjustBitstring, 7, 9));
                 $thisfile_riff['rgad']['peakamplitude'] = $thisfile_riff_raw_rgad['fPeakAmplitude'];
                 if ($thisfile_riff_raw_rgad_track['name'] != 0 && $thisfile_riff_raw_rgad_track['originator'] != 0) {
                     $thisfile_riff['rgad']['track']['name'] = getid3_lib::RGADnameLookup($thisfile_riff_raw_rgad_track['name']);
                     $thisfile_riff['rgad']['track']['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_riff_raw_rgad_track['originator']);
                     $thisfile_riff['rgad']['track']['adjustment'] = getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_track['adjustment'], $thisfile_riff_raw_rgad_track['signbit']);
                 }
                 if ($thisfile_riff_raw_rgad_album['name'] != 0 && $thisfile_riff_raw_rgad_album['originator'] != 0) {
                     $thisfile_riff['rgad']['album']['name'] = getid3_lib::RGADnameLookup($thisfile_riff_raw_rgad_album['name']);
                     $thisfile_riff['rgad']['album']['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_riff_raw_rgad_album['originator']);
                     $thisfile_riff['rgad']['album']['adjustment'] = getid3_lib::RGADadjustmentLookup($thisfile_riff_raw_rgad_album['adjustment'], $thisfile_riff_raw_rgad_album['signbit']);
                 }
             }
             if (isset($thisfile_riff_WAVE['fact'][0]['data'])) {
                 $thisfile_riff_raw['fact']['NumberOfSamples'] = $this->EitherEndian2Int(substr($thisfile_riff_WAVE['fact'][0]['data'], 0, 4));
                 // This should be a good way of calculating exact playtime,
                 // but some sample files have had incorrect number of samples,
                 // so cannot use this method
                 // if (!empty($thisfile_riff_raw['fmt ']['nSamplesPerSec'])) {
                 //     $info['playtime_seconds'] = (float) $thisfile_riff_raw['fact']['NumberOfSamples'] / $thisfile_riff_raw['fmt ']['nSamplesPerSec'];
                 // }
             }
             if (!empty($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'])) {
                 $thisfile_audio['bitrate'] = getid3_lib::CastAsInt($thisfile_riff_raw['fmt ']['nAvgBytesPerSec'] * 8);
             }
             if (isset($thisfile_riff_WAVE['bext'][0]['data'])) {
                 // shortcut
                 $thisfile_riff_WAVE_bext_0 =& $thisfile_riff_WAVE['bext'][0];
                 $thisfile_riff_WAVE_bext_0['title'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 0, 256));
                 $thisfile_riff_WAVE_bext_0['author'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 256, 32));
                 $thisfile_riff_WAVE_bext_0['reference'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 288, 32));
                 $thisfile_riff_WAVE_bext_0['origin_date'] = substr($thisfile_riff_WAVE_bext_0['data'], 320, 10);
                 $thisfile_riff_WAVE_bext_0['origin_time'] = substr($thisfile_riff_WAVE_bext_0['data'], 330, 8);
                 $thisfile_riff_WAVE_bext_0['time_reference'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 338, 8));
                 $thisfile_riff_WAVE_bext_0['bwf_version'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 346, 1));
                 $thisfile_riff_WAVE_bext_0['reserved'] = substr($thisfile_riff_WAVE_bext_0['data'], 347, 254);
                 $thisfile_riff_WAVE_bext_0['coding_history'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_bext_0['data'], 601)));
                 if (preg_match('#^([0-9]{4}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_date'], $matches_bext_date)) {
                     if (preg_match('#^([0-9]{2}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_time'], $matches_bext_time)) {
                         list($dummy, $bext_timestamp['year'], $bext_timestamp['month'], $bext_timestamp['day']) = $matches_bext_date;
                         list($dummy, $bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second']) = $matches_bext_time;
                         $thisfile_riff_WAVE_bext_0['origin_date_unix'] = gmmktime($bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second'], $bext_timestamp['month'], $bext_timestamp['day'], $bext_timestamp['year']);
                     } else {
                         $info['warning'][] = 'RIFF.WAVE.BEXT.origin_time is invalid';
                     }
                 } else {
                     $info['warning'][] = 'RIFF.WAVE.BEXT.origin_date is invalid';
                 }
                 $thisfile_riff['comments']['author'][] = $thisfile_riff_WAVE_bext_0['author'];
                 $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_bext_0['title'];
             }
             if (isset($thisfile_riff_WAVE['MEXT'][0]['data'])) {
                 // shortcut
                 $thisfile_riff_WAVE_MEXT_0 =& $thisfile_riff_WAVE['MEXT'][0];
                 $thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 0, 2));
                 $thisfile_riff_WAVE_MEXT_0['flags']['homogenous'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x1);
                 if ($thisfile_riff_WAVE_MEXT_0['flags']['homogenous']) {
                     $thisfile_riff_WAVE_MEXT_0['flags']['padding'] = $thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x2 ? false : true;
                     $thisfile_riff_WAVE_MEXT_0['flags']['22_or_44'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x4);
                     $thisfile_riff_WAVE_MEXT_0['flags']['free_format'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['sound_information'] & 0x8);
                     $thisfile_riff_WAVE_MEXT_0['nominal_frame_size'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 2, 2));
                 }
                 $thisfile_riff_WAVE_MEXT_0['anciliary_data_length'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 6, 2));
                 $thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_MEXT_0['data'], 8, 2));
                 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_left'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x1);
                 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_free'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x2);
                 $thisfile_riff_WAVE_MEXT_0['flags']['anciliary_data_right'] = (bool) ($thisfile_riff_WAVE_MEXT_0['raw']['anciliary_data_def'] & 0x4);
             }
             if (isset($thisfile_riff_WAVE['cart'][0]['data'])) {
                 // shortcut
                 $thisfile_riff_WAVE_cart_0 =& $thisfile_riff_WAVE['cart'][0];
                 $thisfile_riff_WAVE_cart_0['version'] = substr($thisfile_riff_WAVE_cart_0['data'], 0, 4);
                 $thisfile_riff_WAVE_cart_0['title'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 4, 64));
                 $thisfile_riff_WAVE_cart_0['artist'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 68, 64));
                 $thisfile_riff_WAVE_cart_0['cut_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 132, 64));
                 $thisfile_riff_WAVE_cart_0['client_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 196, 64));
                 $thisfile_riff_WAVE_cart_0['category'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 260, 64));
                 $thisfile_riff_WAVE_cart_0['classification'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 324, 64));
                 $thisfile_riff_WAVE_cart_0['out_cue'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 388, 64));
                 $thisfile_riff_WAVE_cart_0['start_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 452, 10));
                 $thisfile_riff_WAVE_cart_0['start_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 462, 8));
                 $thisfile_riff_WAVE_cart_0['end_date'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 470, 10));
                 $thisfile_riff_WAVE_cart_0['end_time'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 480, 8));
                 $thisfile_riff_WAVE_cart_0['producer_app_id'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 488, 64));
                 $thisfile_riff_WAVE_cart_0['producer_app_version'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 552, 64));
                 $thisfile_riff_WAVE_cart_0['user_defined_text'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 616, 64));
                 $thisfile_riff_WAVE_cart_0['zero_db_reference'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_cart_0['data'], 680, 4), true);
                 for ($i = 0; $i < 8; $i++) {
                     $thisfile_riff_WAVE_cart_0['post_time'][$i]['usage_fourcc'] = substr($thisfile_riff_WAVE_cart_0['data'], 684 + $i * 8, 4);
                     $thisfile_riff_WAVE_cart_0['post_time'][$i]['timer_value'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_cart_0['data'], 684 + $i * 8 + 4, 4));
                 }
                 $thisfile_riff_WAVE_cart_0['url'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 748, 1024));
                 $thisfile_riff_WAVE_cart_0['tag_text'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_cart_0['data'], 1772)));
                 $thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist'];
                 $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_cart_0['title'];
             }
             if (isset($thisfile_riff_WAVE['SNDM'][0]['data'])) {
                 // SoundMiner metadata
                 // shortcuts
                 $thisfile_riff_WAVE_SNDM_0 =& $thisfile_riff_WAVE['SNDM'][0];
                 $thisfile_riff_WAVE_SNDM_0_data =& $thisfile_riff_WAVE_SNDM_0['data'];
                 $SNDM_startoffset = 0;
                 $SNDM_endoffset = $thisfile_riff_WAVE_SNDM_0['size'];
                 while ($SNDM_startoffset < $SNDM_endoffset) {
                     $SNDM_thisTagOffset = 0;
                     $SNDM_thisTagSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4));
                     $SNDM_thisTagOffset += 4;
                     $SNDM_thisTagKey = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 4);
                     $SNDM_thisTagOffset += 4;
                     $SNDM_thisTagDataSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2));
                     $SNDM_thisTagOffset += 2;
                     $SNDM_thisTagDataFlags = getid3_lib::BigEndian2Int(substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, 2));
                     $SNDM_thisTagOffset += 2;
                     $SNDM_thisTagDataText = substr($thisfile_riff_WAVE_SNDM_0_data, $SNDM_startoffset + $SNDM_thisTagOffset, $SNDM_thisTagDataSize);
                     $SNDM_thisTagOffset += $SNDM_thisTagDataSize;
                     if ($SNDM_thisTagSize != 4 + 4 + 2 + 2 + $SNDM_thisTagDataSize) {
                         $info['warning'][] = 'RIFF.WAVE.SNDM.data contains tag not expected length (expected: ' . $SNDM_thisTagSize . ', found: ' . (4 + 4 + 2 + 2 + $SNDM_thisTagDataSize) . ') at offset ' . $SNDM_startoffset . ' (file offset ' . ($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset) . ')';
                         break;
                     } elseif ($SNDM_thisTagSize <= 0) {
                         $info['warning'][] = 'RIFF.WAVE.SNDM.data contains zero-size tag at offset ' . $SNDM_startoffset . ' (file offset ' . ($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset) . ')';
                         break;
                     }
                     $SNDM_startoffset += $SNDM_thisTagSize;
                     $thisfile_riff_WAVE_SNDM_0['parsed_raw'][$SNDM_thisTagKey] = $SNDM_thisTagDataText;
                     if ($parsedkey = self::waveSNDMtagLookup($SNDM_thisTagKey)) {
                         $thisfile_riff_WAVE_SNDM_0['parsed'][$parsedkey] = $SNDM_thisTagDataText;
                     } else {
                         $info['warning'][] = 'RIFF.WAVE.SNDM contains unknown tag "' . $SNDM_thisTagKey . '" at offset ' . $SNDM_startoffset . ' (file offset ' . ($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset) . ')';
                     }
                 }
                 $tagmapping = array('tracktitle' => 'title', 'category' => 'genre', 'cdtitle' => 'album', 'tracktitle' => 'title');
                 foreach ($tagmapping as $fromkey => $tokey) {
                     if (isset($thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey])) {
                         $thisfile_riff['comments'][$tokey][] = $thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey];
                     }
                 }
             }
             if (isset($thisfile_riff_WAVE['iXML'][0]['data'])) {
                 // requires functions simplexml_load_string and get_object_vars
                 if ($parsedXML = getid3_lib::XML2array($thisfile_riff_WAVE['iXML'][0]['data'])) {
                     $thisfile_riff_WAVE['iXML'][0]['parsed'] = $parsedXML;
                     if (isset($parsedXML['SPEED']['MASTER_SPEED'])) {
                         @(list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['MASTER_SPEED']));
                         $thisfile_riff_WAVE['iXML'][0]['master_speed'] = $numerator / ($denominator ? $denominator : 1000);
                     }
                     if (isset($parsedXML['SPEED']['TIMECODE_RATE'])) {
                         @(list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['TIMECODE_RATE']));
                         $thisfile_riff_WAVE['iXML'][0]['timecode_rate'] = $numerator / ($denominator ? $denominator : 1000);
                     }
                     if (isset($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO']) && !empty($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) && !empty($thisfile_riff_WAVE['iXML'][0]['timecode_rate'])) {
                         $samples_since_midnight = floatval(ltrim($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_HI'] . $parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO'], '0'));
                         $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] = $samples_since_midnight / $parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE'];
                         $h = floor($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] / 3600);
                         $m = floor(($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - $h * 3600) / 60);
                         $s = floor($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - $h * 3600 - $m * 60);
                         $f = ($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - $h * 3600 - $m * 60 - $s) * $thisfile_riff_WAVE['iXML'][0]['timecode_rate'];
                         $thisfile_riff_WAVE['iXML'][0]['timecode_string'] = sprintf('%02d:%02d:%02d:%05.2f', $h, $m, $s, $f);
                         $thisfile_riff_WAVE['iXML'][0]['timecode_string_round'] = sprintf('%02d:%02d:%02d:%02d', $h, $m, $s, round($f));
                     }
                     unset($parsedXML);
                 }
             }
             if (!isset($thisfile_audio['bitrate']) && isset($thisfile_riff_audio[$streamindex]['bitrate'])) {
                 $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
                 $info['playtime_seconds'] = (double) (($info['avdataend'] - $info['avdataoffset']) * 8 / $thisfile_audio['bitrate']);
             }
             if (!empty($info['wavpack'])) {
                 $thisfile_audio_dataformat = 'wavpack';
                 $thisfile_audio['bitrate_mode'] = 'vbr';
                 $thisfile_audio['encoder'] = 'WavPack v' . $info['wavpack']['version'];
                 // Reset to the way it was - RIFF parsing will have messed this up
                 $info['avdataend'] = $Original['avdataend'];
                 $thisfile_audio['bitrate'] = ($info['avdataend'] - $info['avdataoffset']) * 8 / $info['playtime_seconds'];
                 $this->fseek($info['avdataoffset'] - 44);
                 $RIFFdata = $this->fread(44);
                 $OrignalRIFFheaderSize = getid3_lib::LittleEndian2Int(substr($RIFFdata, 4, 4)) + 8;
                 $OrignalRIFFdataSize = getid3_lib::LittleEndian2Int(substr($RIFFdata, 40, 4)) + 44;
                 if ($OrignalRIFFheaderSize > $OrignalRIFFdataSize) {
                     $info['avdataend'] -= $OrignalRIFFheaderSize - $OrignalRIFFdataSize;
                     $this->fseek($info['avdataend']);
                     $RIFFdata .= $this->fread($OrignalRIFFheaderSize - $OrignalRIFFdataSize);
                 }
                 // move the data chunk after all other chunks (if any)
                 // so that the RIFF parser doesn't see EOF when trying
                 // to skip over the data chunk
                 $RIFFdata = substr($RIFFdata, 0, 36) . substr($RIFFdata, 44) . substr($RIFFdata, 36, 8);
                 $getid3_riff = new getid3_riff($this->getid3);
                 $getid3_riff->ParseRIFFdata($RIFFdata);
                 unset($getid3_riff);
             }
             if (isset($thisfile_riff_raw['fmt ']['wFormatTag'])) {
                 switch ($thisfile_riff_raw['fmt ']['wFormatTag']) {
                     case 0x1:
                         // PCM
                         if (!empty($info['ac3'])) {
                             // Dolby Digital WAV files masquerade as PCM-WAV, but they're not
                             $thisfile_audio['wformattag'] = 0x2000;
                             $thisfile_audio['codec'] = self::wFormatTagLookup($thisfile_audio['wformattag']);
                             $thisfile_audio['lossless'] = false;
                             $thisfile_audio['bitrate'] = $info['ac3']['bitrate'];
                             $thisfile_audio['sample_rate'] = $info['ac3']['sample_rate'];
                         }
                         if (!empty($info['dts'])) {
                             // Dolby DTS files masquerade as PCM-WAV, but they're not
                             $thisfile_audio['wformattag'] = 0x2001;
                             $thisfile_audio['codec'] = self::wFormatTagLookup($thisfile_audio['wformattag']);
                             $thisfile_audio['lossless'] = false;
                             $thisfile_audio['bitrate'] = $info['dts']['bitrate'];
                             $thisfile_audio['sample_rate'] = $info['dts']['sample_rate'];
                         }
                         break;
                     case 0x8ae:
                         // ClearJump LiteWave
                         $thisfile_audio['bitrate_mode'] = 'vbr';
                         $thisfile_audio_dataformat = 'litewave';
                         //typedef struct tagSLwFormat {
                         //  WORD    m_wCompFormat;     // low byte defines compression method, high byte is compression flags
                         //  DWORD   m_dwScale;         // scale factor for lossy compression
                         //  DWORD   m_dwBlockSize;     // number of samples in encoded blocks
                         //  WORD    m_wQuality;        // alias for the scale factor
                         //  WORD    m_wMarkDistance;   // distance between marks in bytes
                         //  WORD    m_wReserved;
                         //
                         //  //following paramters are ignored if CF_FILESRC is not set
                         //  DWORD   m_dwOrgSize;       // original file size in bytes
                         //  WORD    m_bFactExists;     // indicates if 'fact' chunk exists in the original file
                         //  DWORD   m_dwRiffChunkSize; // riff chunk size in the original file
                         //
                         //  PCMWAVEFORMAT m_OrgWf;     // original wave format
                         // }SLwFormat, *PSLwFormat;
                         // shortcut
                         $thisfile_riff['litewave']['raw'] = array();
                         $riff_litewave =& $thisfile_riff['litewave'];
                         $riff_litewave_raw =& $riff_litewave['raw'];
                         $flags = array('compression_method' => 1, 'compression_flags' => 1, 'm_dwScale' => 4, 'm_dwBlockSize' => 4, 'm_wQuality' => 2, 'm_wMarkDistance' => 2, 'm_wReserved' => 2, 'm_dwOrgSize' => 4, 'm_bFactExists' => 2, 'm_dwRiffChunkSize' => 4);
                         $litewave_offset = 18;
                         foreach ($flags as $flag => $length) {
                             $riff_litewave_raw[$flag] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE['fmt '][0]['data'], $litewave_offset, $length));
                             $litewave_offset += $length;
                         }
                         //$riff_litewave['quality_factor'] = intval(round((2000 - $riff_litewave_raw['m_dwScale']) / 20));
                         $riff_litewave['quality_factor'] = $riff_litewave_raw['m_wQuality'];
                         $riff_litewave['flags']['raw_source'] = $riff_litewave_raw['compression_flags'] & 0x1 ? false : true;
                         $riff_litewave['flags']['vbr_blocksize'] = $riff_litewave_raw['compression_flags'] & 0x2 ? false : true;
                         $riff_litewave['flags']['seekpoints'] = (bool) ($riff_litewave_raw['compression_flags'] & 0x4);
                         $thisfile_audio['lossless'] = $riff_litewave_raw['m_wQuality'] == 100 ? true : false;
                         $thisfile_audio['encoder_options'] = '-q' . $riff_litewave['quality_factor'];
                         break;
                     default:
                         break;
                 }
             }
             if ($info['avdataend'] > $info['filesize']) {
                 switch (!empty($thisfile_audio_dataformat) ? $thisfile_audio_dataformat : '') {
                     case 'wavpack':
                         // WavPack
                     // WavPack
                     case 'lpac':
                         // LPAC
                     // LPAC
                     case 'ofr':
                         // OptimFROG
                     // OptimFROG
                     case 'ofs':
                         // OptimFROG DualStream
                         // lossless compressed audio formats that keep original RIFF headers - skip warning
                         break;
                     case 'litewave':
                         if ($info['avdataend'] - $info['filesize'] == 1) {
                             // LiteWave appears to incorrectly *not* pad actual output file
                             // to nearest WORD boundary so may appear to be short by one
                             // byte, in which case - skip warning
                         } else {
                             // Short by more than one byte, throw warning
                             $info['warning'][] = 'Probably truncated file - expecting ' . $thisfile_riff[$RIFFsubtype]['data'][0]['size'] . ' bytes of data, only found ' . ($info['filesize'] - $info['avdataoffset']) . ' (short by ' . ($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])) . ' bytes)';
                             $info['avdataend'] = $info['filesize'];
                         }
                         break;
                     default:
                         if ($info['avdataend'] - $info['filesize'] == 1 && $thisfile_riff[$RIFFsubtype]['data'][0]['size'] % 2 == 0 && ($info['filesize'] - $info['avdataoffset']) % 2 == 1) {
                             // output file appears to be incorrectly *not* padded to nearest WORD boundary
                             // Output less severe warning
                             $info['warning'][] = 'File should probably be padded to nearest WORD boundary, but it is not (expecting ' . $thisfile_riff[$RIFFsubtype]['data'][0]['size'] . ' bytes of data, only found ' . ($info['filesize'] - $info['avdataoffset']) . ' therefore short by ' . ($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])) . ' bytes)';
                             $info['avdataend'] = $info['filesize'];
                         } else {
                             // Short by more than one byte, throw warning
                             $info['warning'][] = 'Probably truncated file - expecting ' . $thisfile_riff[$RIFFsubtype]['data'][0]['size'] . ' bytes of data, only found ' . ($info['filesize'] - $info['avdataoffset']) . ' (short by ' . ($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])) . ' bytes)';
                             $info['avdataend'] = $info['filesize'];
                         }
                         break;
                 }
             }
             if (!empty($info['mpeg']['audio']['LAME']['audio_bytes'])) {
                 if ($info['avdataend'] - $info['avdataoffset'] - $info['mpeg']['audio']['LAME']['audio_bytes'] == 1) {
                     $info['avdataend']--;
                     $info['warning'][] = 'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored';
                 }
             }
             if (isset($thisfile_audio_dataformat) && $thisfile_audio_dataformat == 'ac3') {
                 unset($thisfile_audio['bits_per_sample']);
                 if (!empty($info['ac3']['bitrate']) && $info['ac3']['bitrate'] != $thisfile_audio['bitrate']) {
                     $thisfile_audio['bitrate'] = $info['ac3']['bitrate'];
                 }
             }
             break;
             // http://en.wikipedia.org/wiki/Audio_Video_Interleave
         // http://en.wikipedia.org/wiki/Audio_Video_Interleave
         case 'AVI ':
             $info['fileformat'] = 'avi';
             $info['mime_type'] = 'video/avi';
             $thisfile_video['bitrate_mode'] = 'vbr';
             // maybe not, but probably
             $thisfile_video['dataformat'] = 'avi';
             if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) {
                 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['movi']['offset'] + 8;
                 if (isset($thisfile_riff['AVIX'])) {
                     $info['avdataend'] = $thisfile_riff['AVIX'][count($thisfile_riff['AVIX']) - 1]['chunks']['movi']['offset'] + $thisfile_riff['AVIX'][count($thisfile_riff['AVIX']) - 1]['chunks']['movi']['size'];
                 } else {
                     $info['avdataend'] = $thisfile_riff['AVI ']['movi']['offset'] + $thisfile_riff['AVI ']['movi']['size'];
                 }
                 if ($info['avdataend'] > $info['filesize']) {
                     $info['warning'][] = 'Probably truncated file - expecting ' . ($info['avdataend'] - $info['avdataoffset']) . ' bytes of data, only found ' . ($info['filesize'] - $info['avdataoffset']) . ' (short by ' . ($info['avdataend'] - $info['filesize']) . ' bytes)';
                     $info['avdataend'] = $info['filesize'];
                 }
             }
             if (isset($thisfile_riff['AVI ']['hdrl']['strl']['indx'])) {
                 //$bIndexType = array(
                 //	0x00 => 'AVI_INDEX_OF_INDEXES',
                 //	0x01 => 'AVI_INDEX_OF_CHUNKS',
                 //	0x80 => 'AVI_INDEX_IS_DATA',
                 //);
                 //$bIndexSubtype = array(
                 //	0x01 => array(
                 //		0x01 => 'AVI_INDEX_2FIELD',
                 //	),
                 //);
                 foreach ($thisfile_riff['AVI ']['hdrl']['strl']['indx'] as $streamnumber => $steamdataarray) {
                     $ahsisd =& $thisfile_riff['AVI ']['hdrl']['strl']['indx'][$streamnumber]['data'];
                     $thisfile_riff_raw['indx'][$streamnumber]['wLongsPerEntry'] = $this->EitherEndian2Int(substr($ahsisd, 0, 2));
                     $thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType'] = $this->EitherEndian2Int(substr($ahsisd, 2, 1));
                     $thisfile_riff_raw['indx'][$streamnumber]['bIndexType'] = $this->EitherEndian2Int(substr($ahsisd, 3, 1));
                     $thisfile_riff_raw['indx'][$streamnumber]['nEntriesInUse'] = $this->EitherEndian2Int(substr($ahsisd, 4, 4));
                     $thisfile_riff_raw['indx'][$streamnumber]['dwChunkId'] = substr($ahsisd, 8, 4);
                     $thisfile_riff_raw['indx'][$streamnumber]['dwReserved'] = $this->EitherEndian2Int(substr($ahsisd, 12, 4));
                     //$thisfile_riff_raw['indx'][$streamnumber]['bIndexType_name']    =    $bIndexType[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']];
                     //$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType_name'] = $bIndexSubtype[$thisfile_riff_raw['indx'][$streamnumber]['bIndexType']][$thisfile_riff_raw['indx'][$streamnumber]['bIndexSubType']];
                     unset($ahsisd);
                 }
             }
             if (isset($thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'])) {
                 $avihData = $thisfile_riff['AVI ']['hdrl']['avih'][$streamindex]['data'];
                 // shortcut
                 $thisfile_riff_raw['avih'] = array();
                 $thisfile_riff_raw_avih =& $thisfile_riff_raw['avih'];
                 $thisfile_riff_raw_avih['dwMicroSecPerFrame'] = $this->EitherEndian2Int(substr($avihData, 0, 4));
                 // frame display rate (or 0L)
                 if ($thisfile_riff_raw_avih['dwMicroSecPerFrame'] == 0) {
                     $info['error'][] = 'Corrupt RIFF file: avih.dwMicroSecPerFrame == zero';
                     return false;
                 }
                 $flags = array('dwMaxBytesPerSec', 'dwPaddingGranularity', 'dwFlags', 'dwTotalFrames', 'dwInitialFrames', 'dwStreams', 'dwSuggestedBufferSize', 'dwWidth', 'dwHeight', 'dwScale', 'dwRate', 'dwStart', 'dwLength');
                 $avih_offset = 4;
                 foreach ($flags as $flag) {
                     $thisfile_riff_raw_avih[$flag] = $this->EitherEndian2Int(substr($avihData, $avih_offset, 4));
                     $avih_offset += 4;
                 }
                 $flags = array('hasindex' => 0x10, 'mustuseindex' => 0x20, 'interleaved' => 0x100, 'trustcktype' => 0x800, 'capturedfile' => 0x10000, 'copyrighted' => 0x20010);
                 foreach ($flags as $flag => $value) {
                     $thisfile_riff_raw_avih['flags'][$flag] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & $value);
                 }
                 // shortcut
                 $thisfile_riff_video[$streamindex] = array();
                 $thisfile_riff_video_current =& $thisfile_riff_video[$streamindex];
                 if ($thisfile_riff_raw_avih['dwWidth'] > 0) {
                     $thisfile_riff_video_current['frame_width'] = $thisfile_riff_raw_avih['dwWidth'];
                     $thisfile_video['resolution_x'] = $thisfile_riff_video_current['frame_width'];
                 }
                 if ($thisfile_riff_raw_avih['dwHeight'] > 0) {
                     $thisfile_riff_video_current['frame_height'] = $thisfile_riff_raw_avih['dwHeight'];
                     $thisfile_video['resolution_y'] = $thisfile_riff_video_current['frame_height'];
                 }
                 if ($thisfile_riff_raw_avih['dwTotalFrames'] > 0) {
                     $thisfile_riff_video_current['total_frames'] = $thisfile_riff_raw_avih['dwTotalFrames'];
                     $thisfile_video['total_frames'] = $thisfile_riff_video_current['total_frames'];
                 }
                 $thisfile_riff_video_current['frame_rate'] = round(1000000 / $thisfile_riff_raw_avih['dwMicroSecPerFrame'], 3);
                 $thisfile_video['frame_rate'] = $thisfile_riff_video_current['frame_rate'];
             }
             if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][0]['data'])) {
                 if (is_array($thisfile_riff['AVI ']['hdrl']['strl']['strh'])) {
                     for ($i = 0; $i < count($thisfile_riff['AVI ']['hdrl']['strl']['strh']); $i++) {
                         if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'])) {
                             $strhData = $thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'];
                             $strhfccType = substr($strhData, 0, 4);
                             if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'])) {
                                 $strfData = $thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'];
                                 // shortcut
                                 $thisfile_riff_raw_strf_strhfccType_streamindex =& $thisfile_riff_raw['strf'][$strhfccType][$streamindex];
                                 switch ($strhfccType) {
                                     case 'auds':
                                         $thisfile_audio['bitrate_mode'] = 'cbr';
                                         $thisfile_audio_dataformat = 'wav';
                                         if (isset($thisfile_riff_audio) && is_array($thisfile_riff_audio)) {
                                             $streamindex = count($thisfile_riff_audio);
                                         }
                                         $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($strfData);
                                         $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
                                         // shortcut
                                         $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
                                         $thisfile_audio_streams_currentstream =& $thisfile_audio['streams'][$streamindex];
                                         if ($thisfile_audio_streams_currentstream['bits_per_sample'] == 0) {
                                             unset($thisfile_audio_streams_currentstream['bits_per_sample']);
                                         }
                                         $thisfile_audio_streams_currentstream['wformattag'] = $thisfile_audio_streams_currentstream['raw']['wFormatTag'];
                                         unset($thisfile_audio_streams_currentstream['raw']);
                                         // shortcut
                                         $thisfile_riff_raw['strf'][$strhfccType][$streamindex] = $thisfile_riff_audio[$streamindex]['raw'];
                                         unset($thisfile_riff_audio[$streamindex]['raw']);
                                         $thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
                                         $thisfile_audio['lossless'] = false;
                                         switch ($thisfile_riff_raw_strf_strhfccType_streamindex['wFormatTag']) {
                                             case 0x1:
                                                 // PCM
                                                 $thisfile_audio_dataformat = 'wav';
                                                 $thisfile_audio['lossless'] = true;
                                                 break;
                                             case 0x50:
                                                 // MPEG Layer 2 or Layer 1
                                                 $thisfile_audio_dataformat = 'mp2';
                                                 // Assume Layer-2
                                                 break;
                                             case 0x55:
                                                 // MPEG Layer 3
                                                 $thisfile_audio_dataformat = 'mp3';
                                                 break;
                                             case 0xff:
                                                 // AAC
                                                 $thisfile_audio_dataformat = 'aac';
                                                 break;
                                             case 0x161:
                                                 // Windows Media v7 / v8 / v9
                                             // Windows Media v7 / v8 / v9
                                             case 0x162:
                                                 // Windows Media Professional v9
                                             // Windows Media Professional v9
                                             case 0x163:
                                                 // Windows Media Lossess v9
                                                 $thisfile_audio_dataformat = 'wma';
                                                 break;
                                             case 0x2000:
                                                 // AC-3
                                                 $thisfile_audio_dataformat = 'ac3';
                                                 break;
                                             case 0x2001:
                                                 // DTS
                                                 $thisfile_audio_dataformat = 'dts';
                                                 break;
                                             default:
                                                 $thisfile_audio_dataformat = 'wav';
                                                 break;
                                         }
                                         $thisfile_audio_streams_currentstream['dataformat'] = $thisfile_audio_dataformat;
                                         $thisfile_audio_streams_currentstream['lossless'] = $thisfile_audio['lossless'];
                                         $thisfile_audio_streams_currentstream['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
                                         break;
                                     case 'iavs':
                                     case 'vids':
                                         // shortcut
                                         $thisfile_riff_raw['strh'][$i] = array();
                                         $thisfile_riff_raw_strh_current =& $thisfile_riff_raw['strh'][$i];
                                         $thisfile_riff_raw_strh_current['fccType'] = substr($strhData, 0, 4);
                                         // same as $strhfccType;
                                         $thisfile_riff_raw_strh_current['fccHandler'] = substr($strhData, 4, 4);
                                         $thisfile_riff_raw_strh_current['dwFlags'] = $this->EitherEndian2Int(substr($strhData, 8, 4));
                                         // Contains AVITF_* flags
                                         $thisfile_riff_raw_strh_current['wPriority'] = $this->EitherEndian2Int(substr($strhData, 12, 2));
                                         $thisfile_riff_raw_strh_current['wLanguage'] = $this->EitherEndian2Int(substr($strhData, 14, 2));
                                         $thisfile_riff_raw_strh_current['dwInitialFrames'] = $this->EitherEndian2Int(substr($strhData, 16, 4));
                                         $thisfile_riff_raw_strh_current['dwScale'] = $this->EitherEndian2Int(substr($strhData, 20, 4));
                                         $thisfile_riff_raw_strh_current['dwRate'] = $this->EitherEndian2Int(substr($strhData, 24, 4));
                                         $thisfile_riff_raw_strh_current['dwStart'] = $this->EitherEndian2Int(substr($strhData, 28, 4));
                                         $thisfile_riff_raw_strh_current['dwLength'] = $this->EitherEndian2Int(substr($strhData, 32, 4));
                                         $thisfile_riff_raw_strh_current['dwSuggestedBufferSize'] = $this->EitherEndian2Int(substr($strhData, 36, 4));
                                         $thisfile_riff_raw_strh_current['dwQuality'] = $this->EitherEndian2Int(substr($strhData, 40, 4));
                                         $thisfile_riff_raw_strh_current['dwSampleSize'] = $this->EitherEndian2Int(substr($strhData, 44, 4));
                                         $thisfile_riff_raw_strh_current['rcFrame'] = $this->EitherEndian2Int(substr($strhData, 48, 4));
                                         $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strh_current['fccHandler']);
                                         $thisfile_video['fourcc'] = $thisfile_riff_raw_strh_current['fccHandler'];
                                         if (!$thisfile_riff_video_current['codec'] && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) && self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
                                             $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']);
                                             $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
                                         }
                                         $thisfile_video['codec'] = $thisfile_riff_video_current['codec'];
                                         $thisfile_video['pixel_aspect_ratio'] = (double) 1;
                                         switch ($thisfile_riff_raw_strh_current['fccHandler']) {
                                             case 'HFYU':
                                                 // Huffman Lossless Codec
                                             // Huffman Lossless Codec
                                             case 'IRAW':
                                                 // Intel YUV Uncompressed
                                             // Intel YUV Uncompressed
                                             case 'YUY2':
                                                 // Uncompressed YUV 4:2:2
                                                 $thisfile_video['lossless'] = true;
                                                 break;
                                             default:
                                                 $thisfile_video['lossless'] = false;
                                                 break;
                                         }
                                         switch ($strhfccType) {
                                             case 'vids':
                                                 $thisfile_riff_raw_strf_strhfccType_streamindex = self::ParseBITMAPINFOHEADER(substr($strfData, 0, 40), $this->container == 'riff');
                                                 $thisfile_video['bits_per_sample'] = $thisfile_riff_raw_strf_strhfccType_streamindex['biBitCount'];
                                                 if ($thisfile_riff_video_current['codec'] == 'DV') {
                                                     $thisfile_riff_video_current['dv_type'] = 2;
                                                 }
                                                 break;
                                             case 'iavs':
                                                 $thisfile_riff_video_current['dv_type'] = 1;
                                                 break;
                                         }
                                         break;
                                     default:
                                         $info['warning'][] = 'Unhandled fccType for stream (' . $i . '): "' . $strhfccType . '"';
                                         break;
                                 }
                             }
                         }
                         if (isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
                             $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
                             if (self::fourccLookup($thisfile_video['fourcc'])) {
                                 $thisfile_riff_video_current['codec'] = self::fourccLookup($thisfile_video['fourcc']);
                                 $thisfile_video['codec'] = $thisfile_riff_video_current['codec'];
                             }
                             switch ($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']) {
                                 case 'HFYU':
                                     // Huffman Lossless Codec
                                 // Huffman Lossless Codec
                                 case 'IRAW':
                                     // Intel YUV Uncompressed
                                 // Intel YUV Uncompressed
                                 case 'YUY2':
                                     // Uncompressed YUV 4:2:2
                                     $thisfile_video['lossless'] = true;
                                     //$thisfile_video['bits_per_sample'] = 24;
                                     break;
                                 default:
                                     $thisfile_video['lossless'] = false;
                                     //$thisfile_video['bits_per_sample'] = 24;
                                     break;
                             }
                         }
                     }
                 }
             }
             break;
         case 'AMV ':
             $info['fileformat'] = 'amv';
             $info['mime_type'] = 'video/amv';
             $thisfile_video['bitrate_mode'] = 'vbr';
             // it's MJPEG, presumably contant-quality encoding, thereby VBR
             $thisfile_video['dataformat'] = 'mjpeg';
             $thisfile_video['codec'] = 'mjpeg';
             $thisfile_video['lossless'] = false;
             $thisfile_video['bits_per_sample'] = 24;
             $thisfile_audio['dataformat'] = 'adpcm';
             $thisfile_audio['lossless'] = false;
             break;
             // http://en.wikipedia.org/wiki/CD-DA
         // http://en.wikipedia.org/wiki/CD-DA
         case 'CDDA':
             $info['fileformat'] = 'cda';
             unset($info['mime_type']);
             $thisfile_audio_dataformat = 'cda';
             $info['avdataoffset'] = 44;
             if (isset($thisfile_riff['CDDA']['fmt '][0]['data'])) {
                 // shortcut
                 $thisfile_riff_CDDA_fmt_0 =& $thisfile_riff['CDDA']['fmt '][0];
                 $thisfile_riff_CDDA_fmt_0['unknown1'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 0, 2));
                 $thisfile_riff_CDDA_fmt_0['track_num'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 2, 2));
                 $thisfile_riff_CDDA_fmt_0['disc_id'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 4, 4));
                 $thisfile_riff_CDDA_fmt_0['start_offset_frame'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 8, 4));
                 $thisfile_riff_CDDA_fmt_0['playtime_frames'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 12, 4));
                 $thisfile_riff_CDDA_fmt_0['unknown6'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 16, 4));
                 $thisfile_riff_CDDA_fmt_0['unknown7'] = $this->EitherEndian2Int(substr($thisfile_riff_CDDA_fmt_0['data'], 20, 4));
                 $thisfile_riff_CDDA_fmt_0['start_offset_seconds'] = (double) $thisfile_riff_CDDA_fmt_0['start_offset_frame'] / 75;
                 $thisfile_riff_CDDA_fmt_0['playtime_seconds'] = (double) $thisfile_riff_CDDA_fmt_0['playtime_frames'] / 75;
                 $info['comments']['track'] = $thisfile_riff_CDDA_fmt_0['track_num'];
                 $info['playtime_seconds'] = $thisfile_riff_CDDA_fmt_0['playtime_seconds'];
                 // hardcoded data for CD-audio
                 $thisfile_audio['lossless'] = true;
                 $thisfile_audio['sample_rate'] = 44100;
                 $thisfile_audio['channels'] = 2;
                 $thisfile_audio['bits_per_sample'] = 16;
                 $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $thisfile_audio['channels'] * $thisfile_audio['bits_per_sample'];
                 $thisfile_audio['bitrate_mode'] = 'cbr';
             }
             break;
             // http://en.wikipedia.org/wiki/AIFF
         // http://en.wikipedia.org/wiki/AIFF
         case 'AIFF':
         case 'AIFC':
             $info['fileformat'] = 'aiff';
             $info['mime_type'] = 'audio/x-aiff';
             $thisfile_audio['bitrate_mode'] = 'cbr';
             $thisfile_audio_dataformat = 'aiff';
             $thisfile_audio['lossless'] = true;
             if (isset($thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'])) {
                 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'] + 8;
                 $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['SSND'][0]['size'];
                 if ($info['avdataend'] > $info['filesize']) {
                     if ($info['avdataend'] == $info['filesize'] + 1 && $info['filesize'] % 2 == 1) {
                         // structures rounded to 2-byte boundary, but dumb encoders
                         // forget to pad end of file to make this actually work
                     } else {
                         $info['warning'][] = 'Probable truncated AIFF file: expecting ' . $thisfile_riff[$RIFFsubtype]['SSND'][0]['size'] . ' bytes of audio data, only ' . ($info['filesize'] - $info['avdataoffset']) . ' bytes found';
                     }
                     $info['avdataend'] = $info['filesize'];
                 }
             }
             if (isset($thisfile_riff[$RIFFsubtype]['COMM'][0]['data'])) {
                 // shortcut
                 $thisfile_riff_RIFFsubtype_COMM_0_data =& $thisfile_riff[$RIFFsubtype]['COMM'][0]['data'];
                 $thisfile_riff_audio['channels'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 0, 2), true);
                 $thisfile_riff_audio['total_samples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 2, 4), false);
                 $thisfile_riff_audio['bits_per_sample'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 6, 2), true);
                 $thisfile_riff_audio['sample_rate'] = (int) getid3_lib::BigEndian2Float(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 8, 10));
                 if ($thisfile_riff[$RIFFsubtype]['COMM'][0]['size'] > 18) {
                     $thisfile_riff_audio['codec_fourcc'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 18, 4);
                     $CodecNameSize = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_COMM_0_data, 22, 1), false);
                     $thisfile_riff_audio['codec_name'] = substr($thisfile_riff_RIFFsubtype_COMM_0_data, 23, $CodecNameSize);
                     switch ($thisfile_riff_audio['codec_name']) {
                         case 'NONE':
                             $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)';
                             $thisfile_audio['lossless'] = true;
                             break;
                         case '':
                             switch ($thisfile_riff_audio['codec_fourcc']) {
                                 // http://developer.apple.com/qa/snd/snd07.html
                                 case 'sowt':
                                     $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Little-Endian PCM';
                                     $thisfile_audio['lossless'] = true;
                                     break;
                                 case 'twos':
                                     $thisfile_riff_audio['codec_name'] = 'Two\'s Compliment Big-Endian PCM';
                                     $thisfile_audio['lossless'] = true;
                                     break;
                                 default:
                                     break;
                             }
                             break;
                         default:
                             $thisfile_audio['codec'] = $thisfile_riff_audio['codec_name'];
                             $thisfile_audio['lossless'] = false;
                             break;
                     }
                 }
                 $thisfile_audio['channels'] = $thisfile_riff_audio['channels'];
                 if ($thisfile_riff_audio['bits_per_sample'] > 0) {
                     $thisfile_audio['bits_per_sample'] = $thisfile_riff_audio['bits_per_sample'];
                 }
                 $thisfile_audio['sample_rate'] = $thisfile_riff_audio['sample_rate'];
                 if ($thisfile_audio['sample_rate'] == 0) {
                     $info['error'][] = 'Corrupted AIFF file: sample_rate == zero';
                     return false;
                 }
                 $info['playtime_seconds'] = $thisfile_riff_audio['total_samples'] / $thisfile_audio['sample_rate'];
             }
             if (isset($thisfile_riff[$RIFFsubtype]['COMT'])) {
                 $offset = 0;
                 $CommentCount = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false);
                 $offset += 2;
                 for ($i = 0; $i < $CommentCount; $i++) {
                     $info['comments_raw'][$i]['timestamp'] = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 4), false);
                     $offset += 4;
                     $info['comments_raw'][$i]['marker_id'] = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), true);
                     $offset += 2;
                     $CommentLength = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, 2), false);
                     $offset += 2;
                     $info['comments_raw'][$i]['comment'] = substr($thisfile_riff[$RIFFsubtype]['COMT'][0]['data'], $offset, $CommentLength);
                     $offset += $CommentLength;
                     $info['comments_raw'][$i]['timestamp_unix'] = getid3_lib::DateMac2Unix($info['comments_raw'][$i]['timestamp']);
                     $thisfile_riff['comments']['comment'][] = $info['comments_raw'][$i]['comment'];
                 }
             }
             $CommentsChunkNames = array('NAME' => 'title', 'author' => 'artist', '(c) ' => 'copyright', 'ANNO' => 'comment');
             foreach ($CommentsChunkNames as $key => $value) {
                 if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) {
                     $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data'];
                 }
             }
             /*
             				if (isset($thisfile_riff[$RIFFsubtype]['ID3 '])) {
             					getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
             					$getid3_temp = new getID3();
             					$getid3_temp->openfile($this->getid3->filename);
             					$getid3_id3v2 = new getid3_id3v2($getid3_temp);
             					$getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['ID3 '][0]['offset'] + 8;
             					if ($thisfile_riff[$RIFFsubtype]['ID3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
             						$info['id3v2'] = $getid3_temp->info['id3v2'];
             					}
             					unset($getid3_temp, $getid3_id3v2);
             				}
             */
             break;
             // http://en.wikipedia.org/wiki/8SVX
         // http://en.wikipedia.org/wiki/8SVX
         case '8SVX':
             $info['fileformat'] = '8svx';
             $info['mime_type'] = 'audio/8svx';
             $thisfile_audio['bitrate_mode'] = 'cbr';
             $thisfile_audio_dataformat = '8svx';
             $thisfile_audio['bits_per_sample'] = 8;
             $thisfile_audio['channels'] = 1;
             // overridden below, if need be
             if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) {
                 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8;
                 $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['BODY'][0]['size'];
                 if ($info['avdataend'] > $info['filesize']) {
                     $info['warning'][] = 'Probable truncated AIFF file: expecting ' . $thisfile_riff[$RIFFsubtype]['BODY'][0]['size'] . ' bytes of audio data, only ' . ($info['filesize'] - $info['avdataoffset']) . ' bytes found';
                 }
             }
             if (isset($thisfile_riff[$RIFFsubtype]['VHDR'][0]['offset'])) {
                 // shortcut
                 $thisfile_riff_RIFFsubtype_VHDR_0 =& $thisfile_riff[$RIFFsubtype]['VHDR'][0];
                 $thisfile_riff_RIFFsubtype_VHDR_0['oneShotHiSamples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 0, 4));
                 $thisfile_riff_RIFFsubtype_VHDR_0['repeatHiSamples'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 4, 4));
                 $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerHiCycle'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 8, 4));
                 $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 12, 2));
                 $thisfile_riff_RIFFsubtype_VHDR_0['ctOctave'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 14, 1));
                 $thisfile_riff_RIFFsubtype_VHDR_0['sCompression'] = getid3_lib::BigEndian2Int(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 15, 1));
                 $thisfile_riff_RIFFsubtype_VHDR_0['Volume'] = getid3_lib::FixedPoint16_16(substr($thisfile_riff_RIFFsubtype_VHDR_0['data'], 16, 4));
                 $thisfile_audio['sample_rate'] = $thisfile_riff_RIFFsubtype_VHDR_0['samplesPerSec'];
                 switch ($thisfile_riff_RIFFsubtype_VHDR_0['sCompression']) {
                     case 0:
                         $thisfile_audio['codec'] = 'Pulse Code Modulation (PCM)';
                         $thisfile_audio['lossless'] = true;
                         $ActualBitsPerSample = 8;
                         break;
                     case 1:
                         $thisfile_audio['codec'] = 'Fibonacci-delta encoding';
                         $thisfile_audio['lossless'] = false;
                         $ActualBitsPerSample = 4;
                         break;
                     default:
                         $info['warning'][] = 'Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "' . sCompression . '"';
                         break;
                 }
             }
             if (isset($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'])) {
                 $ChannelsIndex = getid3_lib::BigEndian2Int(substr($thisfile_riff[$RIFFsubtype]['CHAN'][0]['data'], 0, 4));
                 switch ($ChannelsIndex) {
                     case 6:
                         // Stereo
                         $thisfile_audio['channels'] = 2;
                         break;
                     case 2:
                         // Left channel only
                     // Left channel only
                     case 4:
                         // Right channel only
                         $thisfile_audio['channels'] = 1;
                         break;
                     default:
                         $info['warning'][] = 'Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "' . $ChannelsIndex . '"';
                         break;
                 }
             }
             $CommentsChunkNames = array('NAME' => 'title', 'author' => 'artist', '(c) ' => 'copyright', 'ANNO' => 'comment');
             foreach ($CommentsChunkNames as $key => $value) {
                 if (isset($thisfile_riff[$RIFFsubtype][$key][0]['data'])) {
                     $thisfile_riff['comments'][$value][] = $thisfile_riff[$RIFFsubtype][$key][0]['data'];
                 }
             }
             $thisfile_audio['bitrate'] = $thisfile_audio['sample_rate'] * $ActualBitsPerSample * $thisfile_audio['channels'];
             if (!empty($thisfile_audio['bitrate'])) {
                 $info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset']) / ($thisfile_audio['bitrate'] / 8);
             }
             break;
         case 'CDXA':
             $info['fileformat'] = 'vcd';
             // Asume Video CD
             $info['mime_type'] = 'video/mpeg';
             if (!empty($thisfile_riff['CDXA']['data'][0]['size'])) {
                 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio-video.mpeg.php', __FILE__, true);
                 $getid3_temp = new getID3();
                 $getid3_temp->openfile($this->getid3->filename);
                 $getid3_mpeg = new getid3_mpeg($getid3_temp);
                 $getid3_mpeg->Analyze();
                 if (empty($getid3_temp->info['error'])) {
                     $info['audio'] = $getid3_temp->info['audio'];
                     $info['video'] = $getid3_temp->info['video'];
                     $info['mpeg'] = $getid3_temp->info['mpeg'];
                     $info['warning'] = $getid3_temp->info['warning'];
                 }
                 unset($getid3_temp, $getid3_mpeg);
             }
             break;
         default:
             $info['error'][] = 'Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA), found "' . $RIFFsubtype . '" instead';
             //unset($info['fileformat']);
     }
     switch ($RIFFsubtype) {
         case 'WAVE':
         case 'AIFF':
         case 'AIFC':
             $ID3v2_key_good = 'id3 ';
             $ID3v2_keys_bad = array('ID3 ', 'tag ');
             foreach ($ID3v2_keys_bad as $ID3v2_key_bad) {
                 if (isset($thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]) && !array_key_exists($ID3v2_key_good, $thisfile_riff[$RIFFsubtype])) {
                     $thisfile_riff[$RIFFsubtype][$ID3v2_key_good] = $thisfile_riff[$RIFFsubtype][$ID3v2_key_bad];
                     $info['warning'][] = 'mapping "' . $ID3v2_key_bad . '" chunk to "' . $ID3v2_key_good . '"';
                 }
             }
             if (isset($thisfile_riff[$RIFFsubtype]['id3 '])) {
                 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.tag.id3v2.php', __FILE__, true);
                 $getid3_temp = new getID3();
                 $getid3_temp->openfile($this->getid3->filename);
                 $getid3_id3v2 = new getid3_id3v2($getid3_temp);
                 $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['id3 '][0]['offset'] + 8;
                 if ($thisfile_riff[$RIFFsubtype]['id3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
                     $info['id3v2'] = $getid3_temp->info['id3v2'];
                 }
                 unset($getid3_temp, $getid3_id3v2);
             }
             break;
     }
     if (isset($thisfile_riff_WAVE['DISP']) && is_array($thisfile_riff_WAVE['DISP'])) {
         $thisfile_riff['comments']['title'][] = trim(substr($thisfile_riff_WAVE['DISP'][count($thisfile_riff_WAVE['DISP']) - 1]['data'], 4));
     }
     if (isset($thisfile_riff_WAVE['INFO']) && is_array($thisfile_riff_WAVE['INFO'])) {
         self::parseComments($thisfile_riff_WAVE['INFO'], $thisfile_riff['comments']);
     }
     if (isset($thisfile_riff['AVI ']['INFO']) && is_array($thisfile_riff['AVI ']['INFO'])) {
         self::parseComments($thisfile_riff['AVI ']['INFO'], $thisfile_riff['comments']);
     }
     if (empty($thisfile_audio['encoder']) && !empty($info['mpeg']['audio']['LAME']['short_version'])) {
         $thisfile_audio['encoder'] = $info['mpeg']['audio']['LAME']['short_version'];
     }
     if (!isset($info['playtime_seconds'])) {
         $info['playtime_seconds'] = 0;
     }
     if (isset($thisfile_riff_raw['strh'][0]['dwLength']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) {
         // needed for >2GB AVIs where 'avih' chunk only lists number of frames in that chunk, not entire movie
         $info['playtime_seconds'] = $thisfile_riff_raw['strh'][0]['dwLength'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000);
     } elseif (isset($thisfile_riff_raw['avih']['dwTotalFrames']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) {
         $info['playtime_seconds'] = $thisfile_riff_raw['avih']['dwTotalFrames'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000);
     }
     if ($info['playtime_seconds'] > 0) {
         if (isset($thisfile_riff_audio) && isset($thisfile_riff_video)) {
             if (!isset($info['bitrate'])) {
                 $info['bitrate'] = ($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds'] * 8;
             }
         } elseif (isset($thisfile_riff_audio) && !isset($thisfile_riff_video)) {
             if (!isset($thisfile_audio['bitrate'])) {
                 $thisfile_audio['bitrate'] = ($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds'] * 8;
             }
         } elseif (!isset($thisfile_riff_audio) && isset($thisfile_riff_video)) {
             if (!isset($thisfile_video['bitrate'])) {
                 $thisfile_video['bitrate'] = ($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds'] * 8;
             }
         }
     }
     if (isset($thisfile_riff_video) && isset($thisfile_audio['bitrate']) && $thisfile_audio['bitrate'] > 0 && $info['playtime_seconds'] > 0) {
         $info['bitrate'] = ($info['avdataend'] - $info['avdataoffset']) / $info['playtime_seconds'] * 8;
         $thisfile_audio['bitrate'] = 0;
         $thisfile_video['bitrate'] = $info['bitrate'];
         foreach ($thisfile_riff_audio as $channelnumber => $audioinfoarray) {
             $thisfile_video['bitrate'] -= $audioinfoarray['bitrate'];
             $thisfile_audio['bitrate'] += $audioinfoarray['bitrate'];
         }
         if ($thisfile_video['bitrate'] <= 0) {
             unset($thisfile_video['bitrate']);
         }
         if ($thisfile_audio['bitrate'] <= 0) {
             unset($thisfile_audio['bitrate']);
         }
     }
     if (isset($info['mpeg']['audio'])) {
         $thisfile_audio_dataformat = 'mp' . $info['mpeg']['audio']['layer'];
         $thisfile_audio['sample_rate'] = $info['mpeg']['audio']['sample_rate'];
         $thisfile_audio['channels'] = $info['mpeg']['audio']['channels'];
         $thisfile_audio['bitrate'] = $info['mpeg']['audio']['bitrate'];
         $thisfile_audio['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
         if (!empty($info['mpeg']['audio']['codec'])) {
             $thisfile_audio['codec'] = $info['mpeg']['audio']['codec'] . ' ' . $thisfile_audio['codec'];
         }
         if (!empty($thisfile_audio['streams'])) {
             foreach ($thisfile_audio['streams'] as $streamnumber => $streamdata) {
                 if ($streamdata['dataformat'] == $thisfile_audio_dataformat) {
                     $thisfile_audio['streams'][$streamnumber]['sample_rate'] = $thisfile_audio['sample_rate'];
                     $thisfile_audio['streams'][$streamnumber]['channels'] = $thisfile_audio['channels'];
                     $thisfile_audio['streams'][$streamnumber]['bitrate'] = $thisfile_audio['bitrate'];
                     $thisfile_audio['streams'][$streamnumber]['bitrate_mode'] = $thisfile_audio['bitrate_mode'];
                     $thisfile_audio['streams'][$streamnumber]['codec'] = $thisfile_audio['codec'];
                 }
             }
         }
         $getid3_mp3 = new getid3_mp3($this->getid3);
         $thisfile_audio['encoder_options'] = $getid3_mp3->GuessEncoderOptions();
         unset($getid3_mp3);
     }
     if (!empty($thisfile_riff_raw['fmt ']['wBitsPerSample']) && $thisfile_riff_raw['fmt ']['wBitsPerSample'] > 0) {
         switch ($thisfile_audio_dataformat) {
             case 'ac3':
                 // ignore bits_per_sample
                 break;
             default:
                 $thisfile_audio['bits_per_sample'] = $thisfile_riff_raw['fmt ']['wBitsPerSample'];
                 break;
         }
     }
     if (empty($thisfile_riff_raw)) {
         unset($thisfile_riff['raw']);
     }
     if (empty($thisfile_riff_audio)) {
         unset($thisfile_riff['audio']);
     }
     if (empty($thisfile_riff_video)) {
         unset($thisfile_riff['video']);
     }
     return true;
 }
 function Analyze()
 {
     $info =& $this->getid3->info;
     fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);
     while (true) {
         $wavpackheader = fread($this->getid3->fp, 32);
         if (ftell($this->getid3->fp) >= $info['avdataend']) {
             break;
         } elseif (feof($this->getid3->fp)) {
             break;
         } elseif (isset($info['wavpack']['blockheader']['total_samples']) && isset($info['wavpack']['blockheader']['block_samples']) && $info['wavpack']['blockheader']['total_samples'] > 0 && $info['wavpack']['blockheader']['block_samples'] > 0 && (!isset($info['wavpack']['riff_trailer_size']) || $info['wavpack']['riff_trailer_size'] <= 0) && (isset($info['wavpack']['config_flags']['md5_checksum']) && $info['wavpack']['config_flags']['md5_checksum'] === false || !empty($info['md5_data_source']))) {
             break;
         }
         $blockheader_offset = ftell($this->getid3->fp) - 32;
         $blockheader_magic = substr($wavpackheader, 0, 4);
         $blockheader_size = getid3_lib::LittleEndian2Int(substr($wavpackheader, 4, 4));
         $magic = 'wvpk';
         if ($blockheader_magic != $magic) {
             $info['error'][] = 'Expecting "' . getid3_lib::PrintHexBytes($magic) . '" at offset ' . $blockheader_offset . ', found "' . getid3_lib::PrintHexBytes($blockheader_magic) . '"';
             switch (isset($info['audio']['dataformat']) ? $info['audio']['dataformat'] : '') {
                 case 'wavpack':
                 case 'wvc':
                     break;
                 default:
                     unset($info['fileformat']);
                     unset($info['audio']);
                     unset($info['wavpack']);
                     break;
             }
             return false;
         }
         if (empty($info['wavpack']['blockheader']['block_samples']) || empty($info['wavpack']['blockheader']['total_samples']) || $info['wavpack']['blockheader']['block_samples'] <= 0 || $info['wavpack']['blockheader']['total_samples'] <= 0) {
             // Also, it is possible that the first block might not have
             // any samples (block_samples == 0) and in this case you should skip blocks
             // until you find one with samples because the other information (like
             // total_samples) are not guaranteed to be correct until (block_samples > 0)
             // Finally, I have defined a format for files in which the length is not known
             // (for example when raw files are created using pipes). In these cases
             // total_samples will be -1 and you must seek to the final block to determine
             // the total number of samples.
             $info['audio']['dataformat'] = 'wavpack';
             $info['fileformat'] = 'wavpack';
             $info['audio']['lossless'] = true;
             $info['audio']['bitrate_mode'] = 'vbr';
             $info['wavpack']['blockheader']['offset'] = $blockheader_offset;
             $info['wavpack']['blockheader']['magic'] = $blockheader_magic;
             $info['wavpack']['blockheader']['size'] = $blockheader_size;
             if ($info['wavpack']['blockheader']['size'] >= 0x100000) {
                 $info['error'][] = 'Expecting WavPack block size less than "0x100000", found "' . $info['wavpack']['blockheader']['size'] . '" at offset ' . $info['wavpack']['blockheader']['offset'];
                 switch (isset($info['audio']['dataformat']) ? $info['audio']['dataformat'] : '') {
                     case 'wavpack':
                     case 'wvc':
                         break;
                     default:
                         unset($info['fileformat']);
                         unset($info['audio']);
                         unset($info['wavpack']);
                         break;
                 }
                 return false;
             }
             $info['wavpack']['blockheader']['minor_version'] = ord($wavpackheader[8]);
             $info['wavpack']['blockheader']['major_version'] = ord($wavpackheader[9]);
             if ($info['wavpack']['blockheader']['major_version'] != 4 || $info['wavpack']['blockheader']['minor_version'] < 4 && $info['wavpack']['blockheader']['minor_version'] > 16) {
                 $info['error'][] = 'Expecting WavPack version between "4.2" and "4.16", found version "' . $info['wavpack']['blockheader']['major_version'] . '.' . $info['wavpack']['blockheader']['minor_version'] . '" at offset ' . $info['wavpack']['blockheader']['offset'];
                 switch (isset($info['audio']['dataformat']) ? $info['audio']['dataformat'] : '') {
                     case 'wavpack':
                     case 'wvc':
                         break;
                     default:
                         unset($info['fileformat']);
                         unset($info['audio']);
                         unset($info['wavpack']);
                         break;
                 }
                 return false;
             }
             $info['wavpack']['blockheader']['track_number'] = ord($wavpackheader[10]);
             // unused
             $info['wavpack']['blockheader']['index_number'] = ord($wavpackheader[11]);
             // unused
             $info['wavpack']['blockheader']['total_samples'] = getid3_lib::LittleEndian2Int(substr($wavpackheader, 12, 4));
             $info['wavpack']['blockheader']['block_index'] = getid3_lib::LittleEndian2Int(substr($wavpackheader, 16, 4));
             $info['wavpack']['blockheader']['block_samples'] = getid3_lib::LittleEndian2Int(substr($wavpackheader, 20, 4));
             $info['wavpack']['blockheader']['flags_raw'] = getid3_lib::LittleEndian2Int(substr($wavpackheader, 24, 4));
             $info['wavpack']['blockheader']['crc'] = getid3_lib::LittleEndian2Int(substr($wavpackheader, 28, 4));
             $info['wavpack']['blockheader']['flags']['bytes_per_sample'] = 1 + ($info['wavpack']['blockheader']['flags_raw'] & 0x3);
             $info['wavpack']['blockheader']['flags']['mono'] = (bool) ($info['wavpack']['blockheader']['flags_raw'] & 0x4);
             $info['wavpack']['blockheader']['flags']['hybrid'] = (bool) ($info['wavpack']['blockheader']['flags_raw'] & 0x8);
             $info['wavpack']['blockheader']['flags']['joint_stereo'] = (bool) ($info['wavpack']['blockheader']['flags_raw'] & 0x10);
             $info['wavpack']['blockheader']['flags']['cross_decorrelation'] = (bool) ($info['wavpack']['blockheader']['flags_raw'] & 0x20);
             $info['wavpack']['blockheader']['flags']['hybrid_noiseshape'] = (bool) ($info['wavpack']['blockheader']['flags_raw'] & 0x40);
             $info['wavpack']['blockheader']['flags']['ieee_32bit_float'] = (bool) ($info['wavpack']['blockheader']['flags_raw'] & 0x80);
             $info['wavpack']['blockheader']['flags']['int_32bit'] = (bool) ($info['wavpack']['blockheader']['flags_raw'] & 0x100);
             $info['wavpack']['blockheader']['flags']['hybrid_bitrate_noise'] = (bool) ($info['wavpack']['blockheader']['flags_raw'] & 0x200);
             $info['wavpack']['blockheader']['flags']['hybrid_balance_noise'] = (bool) ($info['wavpack']['blockheader']['flags_raw'] & 0x400);
             $info['wavpack']['blockheader']['flags']['multichannel_initial'] = (bool) ($info['wavpack']['blockheader']['flags_raw'] & 0x800);
             $info['wavpack']['blockheader']['flags']['multichannel_final'] = (bool) ($info['wavpack']['blockheader']['flags_raw'] & 0x1000);
             $info['audio']['lossless'] = !$info['wavpack']['blockheader']['flags']['hybrid'];
         }
         while (!feof($this->getid3->fp) && ftell($this->getid3->fp) < $blockheader_offset + $blockheader_size + 8) {
             $metablock = array('offset' => ftell($this->getid3->fp));
             $metablockheader = fread($this->getid3->fp, 2);
             if (feof($this->getid3->fp)) {
                 break;
             }
             $metablock['id'] = ord($metablockheader[0]);
             $metablock['function_id'] = $metablock['id'] & 0x3f;
             $metablock['function_name'] = $this->WavPackMetablockNameLookup($metablock['function_id']);
             // The 0x20 bit in the id of the meta subblocks (which is defined as
             // ID_OPTIONAL_DATA) is a permanent part of the id. The idea is that
             // if a decoder encounters an id that it does not know about, it uses
             // that "ID_OPTIONAL_DATA" flag to determine what to do. If it is set
             // then the decoder simply ignores the metadata, but if it is zero
             // then the decoder should quit because it means that an understanding
             // of the metadata is required to correctly decode the audio.
             $metablock['non_decoder'] = (bool) ($metablock['id'] & 0x20);
             $metablock['padded_data'] = (bool) ($metablock['id'] & 0x40);
             $metablock['large_block'] = (bool) ($metablock['id'] & 0x80);
             if ($metablock['large_block']) {
                 $metablockheader .= fread($this->getid3->fp, 2);
             }
             $metablock['size'] = getid3_lib::LittleEndian2Int(substr($metablockheader, 1)) * 2;
             // size is stored in words
             $metablock['data'] = null;
             if ($metablock['size'] > 0) {
                 switch ($metablock['function_id']) {
                     case 0x21:
                         // ID_RIFF_HEADER
                     // ID_RIFF_HEADER
                     case 0x22:
                         // ID_RIFF_TRAILER
                     // ID_RIFF_TRAILER
                     case 0x23:
                         // ID_REPLAY_GAIN
                     // ID_REPLAY_GAIN
                     case 0x24:
                         // ID_CUESHEET
                     // ID_CUESHEET
                     case 0x25:
                         // ID_CONFIG_BLOCK
                     // ID_CONFIG_BLOCK
                     case 0x26:
                         // ID_MD5_CHECKSUM
                         $metablock['data'] = fread($this->getid3->fp, $metablock['size']);
                         if ($metablock['padded_data']) {
                             // padded to the nearest even byte
                             $metablock['size']--;
                             $metablock['data'] = substr($metablock['data'], 0, -1);
                         }
                         break;
                     case 0x0:
                         // ID_DUMMY
                     // ID_DUMMY
                     case 0x1:
                         // ID_ENCODER_INFO
                     // ID_ENCODER_INFO
                     case 0x2:
                         // ID_DECORR_TERMS
                     // ID_DECORR_TERMS
                     case 0x3:
                         // ID_DECORR_WEIGHTS
                     // ID_DECORR_WEIGHTS
                     case 0x4:
                         // ID_DECORR_SAMPLES
                     // ID_DECORR_SAMPLES
                     case 0x5:
                         // ID_ENTROPY_VARS
                     // ID_ENTROPY_VARS
                     case 0x6:
                         // ID_HYBRID_PROFILE
                     // ID_HYBRID_PROFILE
                     case 0x7:
                         // ID_SHAPING_WEIGHTS
                     // ID_SHAPING_WEIGHTS
                     case 0x8:
                         // ID_FLOAT_INFO
                     // ID_FLOAT_INFO
                     case 0x9:
                         // ID_INT32_INFO
                     // ID_INT32_INFO
                     case 0xa:
                         // ID_WV_BITSTREAM
                     // ID_WV_BITSTREAM
                     case 0xb:
                         // ID_WVC_BITSTREAM
                     // ID_WVC_BITSTREAM
                     case 0xc:
                         // ID_WVX_BITSTREAM
                     // ID_WVX_BITSTREAM
                     case 0xd:
                         // ID_CHANNEL_INFO
                         fseek($this->getid3->fp, $metablock['offset'] + ($metablock['large_block'] ? 4 : 2) + $metablock['size'], SEEK_SET);
                         break;
                     default:
                         $info['warning'][] = 'Unexpected metablock type "0x' . str_pad(dechex($metablock['function_id']), 2, '0', STR_PAD_LEFT) . '" at offset ' . $metablock['offset'];
                         fseek($this->getid3->fp, $metablock['offset'] + ($metablock['large_block'] ? 4 : 2) + $metablock['size'], SEEK_SET);
                         break;
                 }
                 switch ($metablock['function_id']) {
                     case 0x21:
                         // ID_RIFF_HEADER
                         getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio-video.riff.php', __FILE__, true);
                         $original_wav_filesize = getid3_lib::LittleEndian2Int(substr($metablock['data'], 4, 4));
                         $getid3_temp = new getID3();
                         $getid3_temp->openfile($this->getid3->filename);
                         $getid3_riff = new getid3_riff($getid3_temp);
                         $getid3_riff->ParseRIFFdata($metablock['data']);
                         $metablock['riff'] = $getid3_temp->info['riff'];
                         $info['audio']['sample_rate'] = $getid3_temp->info['riff']['raw']['fmt ']['nSamplesPerSec'];
                         unset($getid3_riff, $getid3_temp);
                         $metablock['riff']['original_filesize'] = $original_wav_filesize;
                         $info['wavpack']['riff_trailer_size'] = $original_wav_filesize - $metablock['riff']['WAVE']['data'][0]['size'] - $metablock['riff']['header_size'];
                         $info['playtime_seconds'] = $info['wavpack']['blockheader']['total_samples'] / $info['audio']['sample_rate'];
                         // Safe RIFF header in case there's a RIFF footer later
                         $metablockRIFFheader = $metablock['data'];
                         break;
                     case 0x22:
                         // ID_RIFF_TRAILER
                         $metablockRIFFfooter = $metablockRIFFheader . $metablock['data'];
                         getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio-video.riff.php', __FILE__, true);
                         $startoffset = $metablock['offset'] + ($metablock['large_block'] ? 4 : 2);
                         $getid3_temp = new getID3();
                         $getid3_temp->openfile($this->getid3->filename);
                         $getid3_temp->info['avdataend'] = $info['avdataend'];
                         $getid3_temp->info['fileformat'] = 'riff';
                         $getid3_riff = new getid3_riff($getid3_temp);
                         $metablock['riff'] = $getid3_riff->ParseRIFF($startoffset, $startoffset + $metablock['size']);
                         if (!empty($metablock['riff']['INFO'])) {
                             $getid3_riff->RIFFcommentsParse($metablock['riff']['INFO'], $metablock['comments']);
                             $info['tags']['riff'] = $metablock['comments'];
                         }
                         unset($getid3_temp, $getid3_riff);
                         break;
                     case 0x23:
                         // ID_REPLAY_GAIN
                         $info['warning'][] = 'WavPack "Replay Gain" contents not yet handled by getID3() in metablock at offset ' . $metablock['offset'];
                         break;
                     case 0x24:
                         // ID_CUESHEET
                         $info['warning'][] = 'WavPack "Cuesheet" contents not yet handled by getID3() in metablock at offset ' . $metablock['offset'];
                         break;
                     case 0x25:
                         // ID_CONFIG_BLOCK
                         $metablock['flags_raw'] = getid3_lib::LittleEndian2Int(substr($metablock['data'], 0, 3));
                         $metablock['flags']['adobe_mode'] = (bool) ($metablock['flags_raw'] & 0x1);
                         // "adobe" mode for 32-bit floats
                         $metablock['flags']['fast_flag'] = (bool) ($metablock['flags_raw'] & 0x2);
                         // fast mode
                         $metablock['flags']['very_fast_flag'] = (bool) ($metablock['flags_raw'] & 0x4);
                         // double fast
                         $metablock['flags']['high_flag'] = (bool) ($metablock['flags_raw'] & 0x8);
                         // high quality mode
                         $metablock['flags']['very_high_flag'] = (bool) ($metablock['flags_raw'] & 0x10);
                         // double high (not used yet)
                         $metablock['flags']['bitrate_kbps'] = (bool) ($metablock['flags_raw'] & 0x20);
                         // bitrate is kbps, not bits / sample
                         $metablock['flags']['auto_shaping'] = (bool) ($metablock['flags_raw'] & 0x40);
                         // automatic noise shaping
                         $metablock['flags']['shape_override'] = (bool) ($metablock['flags_raw'] & 0x80);
                         // shaping mode specified
                         $metablock['flags']['joint_override'] = (bool) ($metablock['flags_raw'] & 0x100);
                         // joint-stereo mode specified
                         $metablock['flags']['copy_time'] = (bool) ($metablock['flags_raw'] & 0x200);
                         // copy file-time from source
                         $metablock['flags']['create_exe'] = (bool) ($metablock['flags_raw'] & 0x400);
                         // create executable
                         $metablock['flags']['create_wvc'] = (bool) ($metablock['flags_raw'] & 0x800);
                         // create correction file
                         $metablock['flags']['optimize_wvc'] = (bool) ($metablock['flags_raw'] & 0x1000);
                         // maximize bybrid compression
                         $metablock['flags']['quality_mode'] = (bool) ($metablock['flags_raw'] & 0x2000);
                         // psychoacoustic quality mode
                         $metablock['flags']['raw_flag'] = (bool) ($metablock['flags_raw'] & 0x4000);
                         // raw mode (not implemented yet)
                         $metablock['flags']['calc_noise'] = (bool) ($metablock['flags_raw'] & 0x8000);
                         // calc noise in hybrid mode
                         $metablock['flags']['lossy_mode'] = (bool) ($metablock['flags_raw'] & 0x10000);
                         // obsolete (for information)
                         $metablock['flags']['extra_mode'] = (bool) ($metablock['flags_raw'] & 0x20000);
                         // extra processing mode
                         $metablock['flags']['skip_wvx'] = (bool) ($metablock['flags_raw'] & 0x40000);
                         // no wvx stream w/ floats & big ints
                         $metablock['flags']['md5_checksum'] = (bool) ($metablock['flags_raw'] & 0x80000);
                         // compute & store MD5 signature
                         $metablock['flags']['quiet_mode'] = (bool) ($metablock['flags_raw'] & 0x100000);
                         // don't report progress %
                         $info['wavpack']['config_flags'] = $metablock['flags'];
                         $info['audio']['encoder_options'] = '';
                         if ($info['wavpack']['blockheader']['flags']['hybrid']) {
                             $info['audio']['encoder_options'] .= ' -b???';
                         }
                         $info['audio']['encoder_options'] .= $metablock['flags']['adobe_mode'] ? ' -a' : '';
                         $info['audio']['encoder_options'] .= $metablock['flags']['optimize_wvc'] ? ' -cc' : '';
                         $info['audio']['encoder_options'] .= $metablock['flags']['create_exe'] ? ' -e' : '';
                         $info['audio']['encoder_options'] .= $metablock['flags']['fast_flag'] ? ' -f' : '';
                         $info['audio']['encoder_options'] .= $metablock['flags']['joint_override'] ? ' -j?' : '';
                         $info['audio']['encoder_options'] .= $metablock['flags']['high_flag'] ? ' -h' : '';
                         $info['audio']['encoder_options'] .= $metablock['flags']['md5_checksum'] ? ' -m' : '';
                         $info['audio']['encoder_options'] .= $metablock['flags']['calc_noise'] ? ' -n' : '';
                         $info['audio']['encoder_options'] .= $metablock['flags']['shape_override'] ? ' -s?' : '';
                         $info['audio']['encoder_options'] .= $metablock['flags']['extra_mode'] ? ' -x?' : '';
                         if (!empty($info['audio']['encoder_options'])) {
                             $info['audio']['encoder_options'] = trim($info['audio']['encoder_options']);
                         } elseif (isset($info['audio']['encoder_options'])) {
                             unset($info['audio']['encoder_options']);
                         }
                         break;
                     case 0x26:
                         // ID_MD5_CHECKSUM
                         if (strlen($metablock['data']) == 16) {
                             $info['md5_data_source'] = strtolower(getid3_lib::PrintHexBytes($metablock['data'], true, false, false));
                         } else {
                             $info['warning'][] = 'Expecting 16 bytes of WavPack "MD5 Checksum" in metablock at offset ' . $metablock['offset'] . ', but found ' . strlen($metablock['data']) . ' bytes';
                         }
                         break;
                     case 0x0:
                         // ID_DUMMY
                     // ID_DUMMY
                     case 0x1:
                         // ID_ENCODER_INFO
                     // ID_ENCODER_INFO
                     case 0x2:
                         // ID_DECORR_TERMS
                     // ID_DECORR_TERMS
                     case 0x3:
                         // ID_DECORR_WEIGHTS
                     // ID_DECORR_WEIGHTS
                     case 0x4:
                         // ID_DECORR_SAMPLES
                     // ID_DECORR_SAMPLES
                     case 0x5:
                         // ID_ENTROPY_VARS
                     // ID_ENTROPY_VARS
                     case 0x6:
                         // ID_HYBRID_PROFILE
                     // ID_HYBRID_PROFILE
                     case 0x7:
                         // ID_SHAPING_WEIGHTS
                     // ID_SHAPING_WEIGHTS
                     case 0x8:
                         // ID_FLOAT_INFO
                     // ID_FLOAT_INFO
                     case 0x9:
                         // ID_INT32_INFO
                     // ID_INT32_INFO
                     case 0xa:
                         // ID_WV_BITSTREAM
                     // ID_WV_BITSTREAM
                     case 0xb:
                         // ID_WVC_BITSTREAM
                     // ID_WVC_BITSTREAM
                     case 0xc:
                         // ID_WVX_BITSTREAM
                     // ID_WVX_BITSTREAM
                     case 0xd:
                         // ID_CHANNEL_INFO
                         unset($metablock);
                         break;
                 }
             }
             if (!empty($metablock)) {
                 $info['wavpack']['metablocks'][] = $metablock;
             }
         }
     }
     $info['audio']['encoder'] = 'WavPack v' . $info['wavpack']['blockheader']['major_version'] . '.' . str_pad($info['wavpack']['blockheader']['minor_version'], 2, '0', STR_PAD_LEFT);
     $info['audio']['bits_per_sample'] = $info['wavpack']['blockheader']['flags']['bytes_per_sample'] * 8;
     $info['audio']['channels'] = $info['wavpack']['blockheader']['flags']['mono'] ? 1 : 2;
     if (!empty($info['playtime_seconds'])) {
         $info['audio']['bitrate'] = ($info['avdataend'] - $info['avdataoffset']) * 8 / $info['playtime_seconds'];
     } else {
         $info['audio']['dataformat'] = 'wvc';
     }
     return true;
 }
<?php

/////////////////////////////////////////////////////////////////
/// getID3() by James Heinrich <*****@*****.**>               //
//  available at http://getid3.sourceforge.net                 //
//            or http://www.getid3.org                         //
/////////////////////////////////////////////////////////////////
// See readme.txt for more details                             //
/////////////////////////////////////////////////////////////////
///                                                            //
// module.tag.id3v2.php                                        //
// module for analyzing ID3v2 tags                             //
// dependencies: module.tag.id3v1.php                          //
//                                                            ///
/////////////////////////////////////////////////////////////////
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.tag.id3v1.php', __FILE__, true);
class getid3_id3v2
{
    function getid3_id3v2(&$fd, &$ThisFileInfo, $StartingOffset = 0)
    {
        //    Overall tag structure:
        //        +-----------------------------+
        //        |      Header (10 bytes)      |
        //        +-----------------------------+
        //        |       Extended Header       |
        //        | (variable length, OPTIONAL) |
        //        +-----------------------------+
        //        |   Frames (variable length)  |
        //        +-----------------------------+
        //        |           Padding           |
        //        | (variable length, OPTIONAL) |
 function analyze($filename)
 {
     if (!empty($this->startup_error)) {
         return $this->error($this->startup_error);
     }
     if (!empty($this->startup_warning)) {
         $this->warning($this->startup_warning);
     }
     // init result array and set parameters
     $this->info = array();
     $this->info['GETID3_VERSION'] = GETID3_VERSION;
     // Check encoding/iconv support
     if (!function_exists('iconv') && !in_array($this->encoding, array('ISO-8859-1', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'UTF-16'))) {
         $errormessage = 'iconv() support is needed for encodings other than ISO-8859-1, UTF-8, UTF-16LE, UTF16-BE, UTF-16. ';
         if (GETID3_OS_ISWINDOWS) {
             $errormessage .= 'PHP does not have iconv() support. Please enable php_iconv.dll in php.ini, and copy iconv.dll from c:/php/dlls to c:/windows/system32';
         } else {
             $errormessage .= 'PHP is not compiled with iconv() support. Please recompile with the --with-iconv switch';
         }
         return $this->error($errormessage);
     }
     // Disable magic_quotes_runtime, if neccesary
     $old_magic_quotes_runtime = get_magic_quotes_runtime();
     // store current setting of magic_quotes_runtime
     if ($old_magic_quotes_runtime) {
         set_magic_quotes_runtime(0);
         // turn off magic_quotes_runtime
         if (get_magic_quotes_runtime()) {
             return $this->error('Could not disable magic_quotes_runtime - getID3() cannot work properly with this setting enabled');
         }
     }
     // remote files not supported
     if (preg_match('/^(ht|f)tp:\\/\\//', $filename)) {
         return $this->error('Remote files are not supported in this version of getID3() - please copy the file locally first');
     }
     // open local file
     if (!($fp = @fopen($filename, 'rb'))) {
         return $this->error('Could not open file "' . $filename . '"');
     }
     // set parameters
     $this->info['filesize'] = filesize($filename);
     // option_max_2gb_check
     if ($this->option_max_2gb_check) {
         // PHP doesn't support integers larger than 31-bit (~2GB)
         // filesize() simply returns (filesize % (pow(2, 32)), no matter the actual filesize
         // ftell() returns 0 if seeking to the end is beyond the range of unsigned integer
         fseek($fp, 0, SEEK_END);
         if ($this->info['filesize'] != 0 && ftell($fp) == 0 || $this->info['filesize'] < 0 || ftell($fp) < 0) {
             unset($this->info['filesize']);
             fclose($fp);
             return $this->error('File is most likely larger than 2GB and is not supported by PHP');
         }
     }
     // set more parameters
     $this->info['avdataoffset'] = 0;
     $this->info['avdataend'] = $this->info['filesize'];
     $this->info['fileformat'] = '';
     // filled in later
     $this->info['audio']['dataformat'] = '';
     // filled in later, unset if not used
     $this->info['video']['dataformat'] = '';
     // filled in later, unset if not used
     $this->info['tags'] = array();
     // filled in later, unset if not used
     $this->info['error'] = array();
     // filled in later, unset if not used
     $this->info['warning'] = array();
     // filled in later, unset if not used
     $this->info['comments'] = array();
     // filled in later, unset if not used
     $this->info['encoding'] = $this->encoding;
     // required by id3v2 and iso modules - can be unset at the end if desired
     // set redundant parameters - might be needed in some include file
     $this->info['filename'] = basename($filename);
     $this->info['filepath'] = str_replace('\\', '/', realpath(dirname($filename)));
     $this->info['filenamepath'] = $this->info['filepath'] . '/' . $this->info['filename'];
     // handle ID3v2 tag - done first - already at beginning of file
     // ID3v2 detection (even if not parsing) is always done otherwise fileformat is much harder to detect
     if ($this->option_tag_id3v2) {
         $GETID3_ERRORARRAY =& $this->info['warning'];
         if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.tag.id3v2.php', __FILE__, false)) {
             $tag = new getid3_id3v2($fp, $this->info);
         }
     } else {
         fseek($fp, 0, SEEK_SET);
         $header = fread($fp, 10);
         if (substr($header, 0, 3) == 'ID3') {
             $this->info['id3v2']['header'] = true;
             $this->info['id3v2']['majorversion'] = ord($header[3]);
             $this->info['id3v2']['minorversion'] = ord($header[4]);
             $this->info['id3v2']['headerlength'] = getid3_lib::BigEndian2Int(substr($header, 6, 4), 1) + 10;
             // length of ID3v2 tag in 10-byte header doesn't include 10-byte header length
             $this->info['id3v2']['tag_offset_start'] = 0;
             $this->info['id3v2']['tag_offset_end'] = $this->info['id3v2']['tag_offset_start'] + $this->info['id3v2']['headerlength'];
             $this->info['avdataoffset'] = $this->info['id3v2']['tag_offset_end'];
         }
     }
     // handle ID3v1 tag
     if ($this->option_tag_id3v1) {
         if (!@(include_once GETID3_INCLUDEPATH . 'module.tag.id3v1.php')) {
             return $this->error('module.tag.id3v1.php is missing - you may disable option_tag_id3v1.');
         }
         $tag = new getid3_id3v1($fp, $this->info);
     }
     // handle APE tag
     if ($this->option_tag_apetag) {
         if (!@(include_once GETID3_INCLUDEPATH . 'module.tag.apetag.php')) {
             return $this->error('module.tag.apetag.php is missing - you may disable option_tag_apetag.');
         }
         $tag = new getid3_apetag($fp, $this->info);
     }
     // handle lyrics3 tag
     if ($this->option_tag_lyrics3) {
         if (!@(include_once GETID3_INCLUDEPATH . 'module.tag.lyrics3.php')) {
             return $this->error('module.tag.lyrics3.php is missing - you may disable option_tag_lyrics3.');
         }
         $tag = new getid3_lyrics3($fp, $this->info);
     }
     // read 32 kb file data
     fseek($fp, $this->info['avdataoffset'], SEEK_SET);
     $formattest = fread($fp, 32774);
     // determine format
     $determined_format = $this->GetFileFormat($formattest, $filename);
     // unable to determine file format
     if (!$determined_format) {
         fclose($fp);
         return $this->error('unable to determine file format');
     }
     // check for illegal ID3 tags
     if (isset($determined_format['fail_id3']) && (in_array('id3v1', $this->info['tags']) || in_array('id3v2', $this->info['tags']))) {
         if ($determined_format['fail_id3'] === 'ERROR') {
             fclose($fp);
             return $this->error('ID3 tags not allowed on this file type.');
         } elseif ($determined_format['fail_id3'] === 'WARNING') {
             $this->info['warning'][] = 'ID3 tags not allowed on this file type.';
         }
     }
     // check for illegal APE tags
     if (isset($determined_format['fail_ape']) && in_array('ape', $this->info['tags'])) {
         if ($determined_format['fail_ape'] === 'ERROR') {
             fclose($fp);
             return $this->error('APE tags not allowed on this file type.');
         } elseif ($determined_format['fail_ape'] === 'WARNING') {
             $this->info['warning'][] = 'APE tags not allowed on this file type.';
         }
     }
     // set mime type
     $this->info['mime_type'] = $determined_format['mime_type'];
     // supported format signature pattern detected, but module deleted
     if (!file_exists(GETID3_INCLUDEPATH . $determined_format['include'])) {
         fclose($fp);
         return $this->error('Format not supported, module, ' . $determined_format['include'] . ', was removed.');
     }
     // module requires iconv support
     if (!function_exists('iconv') && @$determined_format['iconv_req']) {
         return $this->error('iconv support is required for this module (' . $determined_format['include'] . ').');
     }
     // include module
     include_once GETID3_INCLUDEPATH . $determined_format['include'];
     // instantiate module class
     $class_name = 'getid3_' . $determined_format['module'];
     if (!class_exists($class_name)) {
         return $this->error('Format not supported, module, ' . $determined_format['include'] . ', is corrupt.');
     }
     if (isset($determined_format['option'])) {
         $class = new $class_name($fp, $this->info, $determined_format['option']);
     } else {
         $class = new $class_name($fp, $this->info);
     }
     // close file
     fclose($fp);
     // process all tags - copy to 'tags' and convert charsets
     if ($this->option_tags_process) {
         $this->HandleAllTags();
     }
     // perform more calculations
     if ($this->option_extra_info) {
         $this->ChannelsBitratePlaytimeCalculations();
         $this->CalculateCompressionRatioVideo();
         $this->CalculateCompressionRatioAudio();
         $this->CalculateReplayGain();
         $this->ProcessAudioStreams();
     }
     // get the MD5 sum of the audio/video portion of the file - without ID3/APE/Lyrics3/etc header/footer tags
     if ($this->option_md5_data) {
         // do not cald md5_data if md5_data_source is present - set by flac only - future MPC/SV8 too
         if (!$this->option_md5_data_source || empty($this->info['md5_data_source'])) {
             $this->getHashdata('md5');
         }
     }
     // get the SHA1 sum of the audio/video portion of the file - without ID3/APE/Lyrics3/etc header/footer tags
     if ($this->option_sha1_data) {
         $this->getHashdata('sha1');
     }
     // remove undesired keys
     $this->CleanUp();
     // restore magic_quotes_runtime setting
     set_magic_quotes_runtime($old_magic_quotes_runtime);
     // return info array
     return $this->info;
 }
 public function Analyze()
 {
     $info =& $this->getid3->info;
     // parse container
     try {
         $this->parseEBML($info);
     } catch (Exception $e) {
         $info['error'][] = 'EBML parser: ' . $e->getMessage();
     }
     // calculate playtime
     if (isset($info['matroska']['info']) && is_array($info['matroska']['info'])) {
         foreach ($info['matroska']['info'] as $key => $infoarray) {
             if (isset($infoarray['Duration'])) {
                 // TimecodeScale is how many nanoseconds each Duration unit is
                 $info['playtime_seconds'] = $infoarray['Duration'] * ((isset($infoarray['TimecodeScale']) ? $infoarray['TimecodeScale'] : 1000000) / 1000000000);
                 break;
             }
         }
     }
     // extract tags
     if (isset($info['matroska']['tags']) && is_array($info['matroska']['tags'])) {
         foreach ($info['matroska']['tags'] as $key => $infoarray) {
             $this->ExtractCommentsSimpleTag($infoarray);
         }
     }
     // process tracks
     if (isset($info['matroska']['tracks']['tracks']) && is_array($info['matroska']['tracks']['tracks'])) {
         foreach ($info['matroska']['tracks']['tracks'] as $key => $trackarray) {
             $track_info = array();
             $track_info['dataformat'] = self::CodecIDtoCommonName($trackarray['CodecID']);
             $track_info['default'] = isset($trackarray['FlagDefault']) ? $trackarray['FlagDefault'] : true;
             if (isset($trackarray['Name'])) {
                 $track_info['name'] = $trackarray['Name'];
             }
             switch ($trackarray['TrackType']) {
                 case 1:
                     // Video
                     $track_info['resolution_x'] = $trackarray['PixelWidth'];
                     $track_info['resolution_y'] = $trackarray['PixelHeight'];
                     $track_info['display_unit'] = self::displayUnit(isset($trackarray['DisplayUnit']) ? $trackarray['DisplayUnit'] : 0);
                     $track_info['display_x'] = isset($trackarray['DisplayWidth']) ? $trackarray['DisplayWidth'] : $trackarray['PixelWidth'];
                     $track_info['display_y'] = isset($trackarray['DisplayHeight']) ? $trackarray['DisplayHeight'] : $trackarray['PixelHeight'];
                     if (isset($trackarray['PixelCropBottom'])) {
                         $track_info['crop_bottom'] = $trackarray['PixelCropBottom'];
                     }
                     if (isset($trackarray['PixelCropTop'])) {
                         $track_info['crop_top'] = $trackarray['PixelCropTop'];
                     }
                     if (isset($trackarray['PixelCropLeft'])) {
                         $track_info['crop_left'] = $trackarray['PixelCropLeft'];
                     }
                     if (isset($trackarray['PixelCropRight'])) {
                         $track_info['crop_right'] = $trackarray['PixelCropRight'];
                     }
                     if (isset($trackarray['DefaultDuration'])) {
                         $track_info['frame_rate'] = round(1000000000 / $trackarray['DefaultDuration'], 3);
                     }
                     if (isset($trackarray['CodecName'])) {
                         $track_info['codec'] = $trackarray['CodecName'];
                     }
                     switch ($trackarray['CodecID']) {
                         case 'V_MS/VFW/FOURCC':
                             getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio-video.riff.php', __FILE__, true);
                             $parsed = getid3_riff::ParseBITMAPINFOHEADER($trackarray['CodecPrivate']);
                             $track_info['codec'] = getid3_riff::fourccLookup($parsed['fourcc']);
                             $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $parsed;
                             break;
                             /*case 'V_MPEG4/ISO/AVC':
                             		$h264['profile']    = getid3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], 1, 1));
                             		$h264['level']      = getid3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], 3, 1));
                             		$rn                 = getid3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], 4, 1));
                             		$h264['NALUlength'] = ($rn & 3) + 1;
                             		$rn                 = getid3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], 5, 1));
                             		$nsps               = ($rn & 31);
                             		$offset             = 6;
                             		for ($i = 0; $i < $nsps; $i ++) {
                             			$length        = getid3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], $offset, 2));
                             			$h264['SPS'][] = substr($trackarray['CodecPrivate'], $offset + 2, $length);
                             			$offset       += 2 + $length;
                             		}
                             		$npps               = getid3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], $offset, 1));
                             		$offset            += 1;
                             		for ($i = 0; $i < $npps; $i ++) {
                             			$length        = getid3_lib::BigEndian2Int(substr($trackarray['CodecPrivate'], $offset, 2));
                             			$h264['PPS'][] = substr($trackarray['CodecPrivate'], $offset + 2, $length);
                             			$offset       += 2 + $length;
                             		}
                             		$info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $h264;
                             		break;*/
                     }
                     $info['video']['streams'][] = $track_info;
                     break;
                 case 2:
                     // Audio
                     $track_info['sample_rate'] = isset($trackarray['SamplingFrequency']) ? $trackarray['SamplingFrequency'] : 8000.0;
                     $track_info['channels'] = isset($trackarray['Channels']) ? $trackarray['Channels'] : 1;
                     $track_info['language'] = isset($trackarray['Language']) ? $trackarray['Language'] : 'eng';
                     if (isset($trackarray['BitDepth'])) {
                         $track_info['bits_per_sample'] = $trackarray['BitDepth'];
                     }
                     if (isset($trackarray['CodecName'])) {
                         $track_info['codec'] = $trackarray['CodecName'];
                     }
                     switch ($trackarray['CodecID']) {
                         case 'A_PCM/INT/LIT':
                         case 'A_PCM/INT/BIG':
                             $track_info['bitrate'] = $trackarray['SamplingFrequency'] * $trackarray['Channels'] * $trackarray['BitDepth'];
                             break;
                         case 'A_AC3':
                         case 'A_DTS':
                         case 'A_MPEG/L3':
                         case 'A_MPEG/L2':
                         case 'A_FLAC':
                             getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.' . ($track_info['dataformat'] == 'mp2' ? 'mp3' : $track_info['dataformat']) . '.php', __FILE__, true);
                             if (!isset($info['matroska']['track_data_offsets'][$trackarray['TrackNumber']])) {
                                 $this->warning('Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because $info[matroska][track_data_offsets][' . $trackarray['TrackNumber'] . '] not set');
                                 break;
                             }
                             // create temp instance
                             $getid3_temp = new getID3();
                             if ($track_info['dataformat'] != 'flac') {
                                 $getid3_temp->openfile($this->getid3->filename);
                             }
                             $getid3_temp->info['avdataoffset'] = $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['offset'];
                             if ($track_info['dataformat'][0] == 'm' || $track_info['dataformat'] == 'flac') {
                                 $getid3_temp->info['avdataend'] = $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['offset'] + $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['length'];
                             }
                             // analyze
                             $class = 'getid3_' . ($track_info['dataformat'] == 'mp2' ? 'mp3' : $track_info['dataformat']);
                             $header_data_key = $track_info['dataformat'][0] == 'm' ? 'mpeg' : $track_info['dataformat'];
                             $getid3_audio = new $class($getid3_temp, __CLASS__);
                             if ($track_info['dataformat'] == 'flac') {
                                 $getid3_audio->AnalyzeString($trackarray['CodecPrivate']);
                             } else {
                                 $getid3_audio->Analyze();
                             }
                             if (!empty($getid3_temp->info[$header_data_key])) {
                                 $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info[$header_data_key];
                                 if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
                                     foreach ($getid3_temp->info['audio'] as $key => $value) {
                                         $track_info[$key] = $value;
                                     }
                                 }
                             } else {
                                 $this->warning('Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because ' . $class . '::Analyze() failed at offset ' . $getid3_temp->info['avdataoffset']);
                             }
                             // copy errors and warnings
                             if (!empty($getid3_temp->info['error'])) {
                                 foreach ($getid3_temp->info['error'] as $newerror) {
                                     $this->warning($class . '() says: [' . $newerror . ']');
                                 }
                             }
                             if (!empty($getid3_temp->info['warning'])) {
                                 foreach ($getid3_temp->info['warning'] as $newerror) {
                                     $this->warning($class . '() says: [' . $newerror . ']');
                                 }
                             }
                             unset($getid3_temp, $getid3_audio);
                             break;
                         case 'A_AAC':
                         case 'A_AAC/MPEG2/LC':
                         case 'A_AAC/MPEG2/LC/SBR':
                         case 'A_AAC/MPEG4/LC':
                         case 'A_AAC/MPEG4/LC/SBR':
                             $this->warning($trackarray['CodecID'] . ' audio data contains no header, audio/video bitrates can\'t be calculated');
                             break;
                         case 'A_VORBIS':
                             if (!isset($trackarray['CodecPrivate'])) {
                                 $this->warning('Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because CodecPrivate data not set');
                                 break;
                             }
                             $vorbis_offset = strpos($trackarray['CodecPrivate'], 'vorbis', 1);
                             if ($vorbis_offset === false) {
                                 $this->warning('Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because CodecPrivate data does not contain "vorbis" keyword');
                                 break;
                             }
                             $vorbis_offset -= 1;
                             getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.ogg.php', __FILE__, true);
                             // create temp instance
                             $getid3_temp = new getID3();
                             // analyze
                             $getid3_ogg = new getid3_ogg($getid3_temp);
                             $oggpageinfo['page_seqno'] = 0;
                             $getid3_ogg->ParseVorbisPageHeader($trackarray['CodecPrivate'], $vorbis_offset, $oggpageinfo);
                             if (!empty($getid3_temp->info['ogg'])) {
                                 $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info['ogg'];
                                 if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
                                     foreach ($getid3_temp->info['audio'] as $key => $value) {
                                         $track_info[$key] = $value;
                                     }
                                 }
                             }
                             // copy errors and warnings
                             if (!empty($getid3_temp->info['error'])) {
                                 foreach ($getid3_temp->info['error'] as $newerror) {
                                     $this->warning('getid3_ogg() says: [' . $newerror . ']');
                                 }
                             }
                             if (!empty($getid3_temp->info['warning'])) {
                                 foreach ($getid3_temp->info['warning'] as $newerror) {
                                     $this->warning('getid3_ogg() says: [' . $newerror . ']');
                                 }
                             }
                             if (!empty($getid3_temp->info['ogg']['bitrate_nominal'])) {
                                 $track_info['bitrate'] = $getid3_temp->info['ogg']['bitrate_nominal'];
                             }
                             unset($getid3_temp, $getid3_ogg, $oggpageinfo, $vorbis_offset);
                             break;
                         case 'A_MS/ACM':
                             getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio-video.riff.php', __FILE__, true);
                             $parsed = getid3_riff::parseWAVEFORMATex($trackarray['CodecPrivate']);
                             foreach ($parsed as $key => $value) {
                                 if ($key != 'raw') {
                                     $track_info[$key] = $value;
                                 }
                             }
                             $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $parsed;
                             break;
                         default:
                             $this->warning('Unhandled audio type "' . (isset($trackarray['CodecID']) ? $trackarray['CodecID'] : '') . '"');
                             break;
                     }
                     $info['audio']['streams'][] = $track_info;
                     break;
             }
         }
         if (!empty($info['video']['streams'])) {
             $info['video'] = self::getDefaultStreamInfo($info['video']['streams']);
         }
         if (!empty($info['audio']['streams'])) {
             $info['audio'] = self::getDefaultStreamInfo($info['audio']['streams']);
         }
     }
     // process attachments
     if (isset($info['matroska']['attachments']) && $this->getid3->option_save_attachments !== getID3::ATTACHMENTS_NONE) {
         foreach ($info['matroska']['attachments'] as $i => $entry) {
             if (strpos($entry['FileMimeType'], 'image/') === 0 && !empty($entry['FileData'])) {
                 $info['matroska']['comments']['picture'][] = array('data' => $entry['FileData'], 'image_mime' => $entry['FileMimeType'], 'filename' => $entry['FileName']);
             }
         }
     }
     // determine mime type
     if (!empty($info['video']['streams'])) {
         $info['mime_type'] = $info['matroska']['doctype'] == 'webm' ? 'video/webm' : 'video/x-matroska';
     } elseif (!empty($info['audio']['streams'])) {
         $info['mime_type'] = $info['matroska']['doctype'] == 'webm' ? 'audio/webm' : 'audio/x-matroska';
     } elseif (isset($info['mime_type'])) {
         unset($info['mime_type']);
     }
     return true;
 }
 function Analyze()
 {
     $info =& $this->getid3->info;
     // http://www.matroska.org/technical/specs/index.html#EBMLBasics
     $offset = $info['avdataoffset'];
     $EBMLdata = '';
     $EBMLdata_offset = $offset;
     if (!getid3_lib::intValueSupported($info['avdataend'])) {
         $this->warnings[] = 'This version of getID3() [' . $this->getid3->version() . '] may or may not correctly handle Matroska files larger than ' . round(PHP_INT_MAX / 1073741824) . 'GB';
     }
     while ($offset < $info['avdataend']) {
         $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
         $top_element_offset = $offset;
         $top_element_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
         $top_element_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
         if ($top_element_length === false) {
             $this->warnings[] = 'invalid chunk length at ' . $top_element_offset;
             $offset = PHP_INT_MAX + 1;
             break;
         }
         $top_element_endoffset = $offset + $top_element_length;
         switch ($top_element_id) {
             case EBML_ID_EBML:
                 $info['fileformat'] = 'matroska';
                 $info['matroska']['header']['offset'] = $top_element_offset;
                 $info['matroska']['header']['length'] = $top_element_length;
                 while ($offset < $top_element_endoffset) {
                     $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                     $element_data = array();
                     $element_data_offset = $offset;
                     $element_data['id'] = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                     $element_data['id_name'] = $this->EBMLidName($element_data['id']);
                     $element_data['length'] = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                     $end_offset = $offset + $element_data['length'];
                     switch ($element_data['id']) {
                         case EBML_ID_VOID:
                             // padding, ignore
                             break;
                         case EBML_ID_EBMLVERSION:
                         case EBML_ID_EBMLREADVERSION:
                         case EBML_ID_EBMLMAXIDLENGTH:
                         case EBML_ID_EBMLMAXSIZELENGTH:
                         case EBML_ID_DOCTYPEVERSION:
                         case EBML_ID_DOCTYPEREADVERSION:
                             $element_data['data'] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $element_data['length']));
                             break;
                         case EBML_ID_DOCTYPE:
                             $element_data['data'] = trim(substr($EBMLdata, $offset - $EBMLdata_offset, $element_data['length']), "");
                             break;
                         case EBML_ID_CRC32:
                             // probably not useful, ignore
                             unset($element_data);
                             break;
                         default:
                             $this->warnings[] = 'Unhandled track.video element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $element_data['id'] . '::' . $element_data['id_name'] . ') at ' . $element_data_offset;
                             break;
                     }
                     $offset = $end_offset;
                     if (!empty($element_data)) {
                         $info['matroska']['header']['elements'][] = $element_data;
                     }
                 }
                 break;
             case EBML_ID_SEGMENT:
                 $info['matroska']['segment'][0]['offset'] = $top_element_offset;
                 $info['matroska']['segment'][0]['length'] = $top_element_length;
                 $segment_key = -1;
                 while ($offset < $info['avdataend']) {
                     $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                     $element_data = array();
                     $element_data['offset'] = $offset;
                     $element_data['id'] = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                     $element_data['id_name'] = $this->EBMLidName($element_data['id']);
                     $element_data['length'] = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                     if ($element_data['length'] === false) {
                         $this->warnings[] = 'invalid chunk length at ' . $element_data['offset'];
                         //$offset = PHP_INT_MAX + 1;
                         $offset = $info['avdataend'];
                         break;
                     }
                     $element_end = $offset + $element_data['length'];
                     switch ($element_data['id']) {
                         //case EBML_ID_CLUSTER:
                         //	// too many cluster entries, probably not useful
                         //	break;
                         case false:
                             $this->warnings[] = 'invalid ID at ' . $element_data['offset'];
                             $offset = $element_end;
                             continue 3;
                         default:
                             $info['matroska']['segments'][] = $element_data;
                             break;
                     }
                     $segment_key++;
                     switch ($element_data['id']) {
                         case EBML_ID_SEEKHEAD:
                             // Contains the position of other level 1 elements
                             while ($offset < $element_end) {
                                 $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                 $seek_entry = array();
                                 $seek_entry['offset'] = $offset;
                                 $seek_entry['id'] = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                 $seek_entry['id_name'] = $this->EBMLidName($seek_entry['id']);
                                 $seek_entry['length'] = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                 $seek_end_offset = $offset + $seek_entry['length'];
                                 switch ($seek_entry['id']) {
                                     case EBML_ID_SEEK:
                                         // Contains a single seek entry to an EBML element
                                         while ($offset < $seek_end_offset) {
                                             $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                             $id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                             $length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                             $value = substr($EBMLdata, $offset - $EBMLdata_offset, $length);
                                             $offset += $length;
                                             switch ($id) {
                                                 case EBML_ID_SEEKID:
                                                     $dummy = 0;
                                                     $seek_entry['target_id'] = $this->readEBMLint($value, $dummy);
                                                     $seek_entry['target_name'] = $this->EBMLidName($seek_entry['target_id']);
                                                     break;
                                                 case EBML_ID_SEEKPOSITION:
                                                     $seek_entry['target_offset'] = $element_data['offset'] + getid3_lib::BigEndian2Int($value);
                                                     break;
                                                 case EBML_ID_CRC32:
                                                     // probably not useful, ignore
                                                     //$seek_entry['crc32'] = getid3_lib::PrintHexBytes($value, true, false, false);
                                                     unset($seek_entry);
                                                     break;
                                                 default:
                                                     $info['error'][] = 'Unhandled segment [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $id . ') at ' . $offset;
                                                     break;
                                             }
                                         }
                                         if (!empty($seek_entry)) {
                                             $info['matroska']['seek'][] = $seek_entry;
                                         }
                                         //switch ($seek_entry['target_id']) {
                                         //	case EBML_ID_CLUSTER:
                                         //		// too many cluster seek points, probably not useful
                                         //		break;
                                         //	default:
                                         //		$info['matroska']['seek'][] = $seek_entry;
                                         //		break;
                                         //}
                                         break;
                                     case EBML_ID_CRC32:
                                         // probably not useful, ignore
                                         break;
                                     default:
                                         $this->warnings[] = 'Unhandled seekhead element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $seek_entry['id'] . '::' . $seek_entry['id_name'] . ') at ' . $offset;
                                         break;
                                 }
                                 $offset = $seek_end_offset;
                             }
                             break;
                         case EBML_ID_TRACKS:
                             // information about all tracks in segment
                             $info['matroska']['tracks'] = $element_data;
                             while ($offset < $element_end) {
                                 $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                 $track_entry = array();
                                 $track_entry['offset'] = $offset;
                                 $track_entry['id'] = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                 $track_entry['id_name'] = $this->EBMLidName($track_entry['id']);
                                 $track_entry['length'] = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                 $track_entry_endoffset = $offset + $track_entry['length'];
                                 // $track_entry['offset'] is not the same as $offset, even though they were set equal a few lines up: $offset has been automagically incremented by readEMLint()
                                 switch ($track_entry['id']) {
                                     case EBML_ID_TRACKENTRY:
                                         //subelements: Describes a track with all elements.
                                         while ($offset < $track_entry_endoffset) {
                                             $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                             $subelement_offset = $offset;
                                             $subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                             $subelement_idname = $this->EBMLidName($subelement_id);
                                             $subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                             $subelement_end = $offset + $subelement_length;
                                             switch ($subelement_id) {
                                                 case EBML_ID_TRACKNUMBER:
                                                 case EBML_ID_TRACKUID:
                                                 case EBML_ID_TRACKTYPE:
                                                 case EBML_ID_MINCACHE:
                                                 case EBML_ID_MAXCACHE:
                                                 case EBML_ID_MAXBLOCKADDITIONID:
                                                 case EBML_ID_DEFAULTDURATION:
                                                     // nanoseconds per frame
                                                     $track_entry[$subelement_idname] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $subelement_length));
                                                     break;
                                                 case EBML_ID_TRACKTIMECODESCALE:
                                                     $track_entry[$subelement_idname] = getid3_lib::BigEndian2Float(substr($EBMLdata, $offset - $EBMLdata_offset, $subelement_length));
                                                     break;
                                                 case EBML_ID_CODECID:
                                                 case EBML_ID_LANGUAGE:
                                                 case EBML_ID_NAME:
                                                 case EBML_ID_CODECNAME:
                                                 case EBML_ID_CODECPRIVATE:
                                                     $track_entry[$subelement_idname] = trim(substr($EBMLdata, $offset - $EBMLdata_offset, $subelement_length), "");
                                                     break;
                                                     // thought maybe it was a nice wFormatTag entry, but it's not :(
                                                     //case EBML_ID_CODECPRIVATE:
                                                     //$track_entry[$subelement_idname] =                             trim(substr($EBMLdata, $offset - $EBMLdata_offset, $subelement_length), "\x00");
                                                     //if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, false)) {
                                                     //	$track_entry[$subelement_idname.'_decoded'] = getid3_riff::RIFFparseWAVEFORMATex($track_entry[$subelement_idname]);
                                                     //	if (isset($track_entry[$subelement_idname.'_decoded']['raw']['wFormatTag'])) {
                                                     //	}
                                                     //} else {
                                                     //	$this->warnings[] = 'failed to include "module.audio-video.riff.php" for parsing codec private data';
                                                     //}
                                                     //break;
                                                 // thought maybe it was a nice wFormatTag entry, but it's not :(
                                                 //case EBML_ID_CODECPRIVATE:
                                                 //$track_entry[$subelement_idname] =                             trim(substr($EBMLdata, $offset - $EBMLdata_offset, $subelement_length), "\x00");
                                                 //if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, false)) {
                                                 //	$track_entry[$subelement_idname.'_decoded'] = getid3_riff::RIFFparseWAVEFORMATex($track_entry[$subelement_idname]);
                                                 //	if (isset($track_entry[$subelement_idname.'_decoded']['raw']['wFormatTag'])) {
                                                 //	}
                                                 //} else {
                                                 //	$this->warnings[] = 'failed to include "module.audio-video.riff.php" for parsing codec private data';
                                                 //}
                                                 //break;
                                                 case EBML_ID_FLAGENABLED:
                                                 case EBML_ID_FLAGDEFAULT:
                                                 case EBML_ID_FLAGFORCED:
                                                 case EBML_ID_FLAGLACING:
                                                 case EBML_ID_CODECDECODEALL:
                                                     $track_entry[$subelement_idname] = (bool) getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $subelement_length));
                                                     break;
                                                 case EBML_ID_VIDEO:
                                                     while ($offset < $subelement_end) {
                                                         $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                                         $sub_subelement_offset = $offset;
                                                         $sub_subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                         $sub_subelement_idname = $this->EBMLidName($sub_subelement_id);
                                                         $sub_subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                         $sub_subelement_end = $offset + $sub_subelement_length;
                                                         switch ($sub_subelement_id) {
                                                             case EBML_ID_PIXELWIDTH:
                                                             case EBML_ID_PIXELHEIGHT:
                                                             case EBML_ID_STEREOMODE:
                                                             case EBML_ID_PIXELCROPBOTTOM:
                                                             case EBML_ID_PIXELCROPTOP:
                                                             case EBML_ID_PIXELCROPLEFT:
                                                             case EBML_ID_PIXELCROPRIGHT:
                                                             case EBML_ID_DISPLAYWIDTH:
                                                             case EBML_ID_DISPLAYHEIGHT:
                                                             case EBML_ID_DISPLAYUNIT:
                                                             case EBML_ID_ASPECTRATIOTYPE:
                                                                 $track_entry[$sub_subelement_idname] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_subelement_length));
                                                                 break;
                                                             case EBML_ID_FLAGINTERLACED:
                                                                 $track_entry[$sub_subelement_idname] = (bool) getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_subelement_length));
                                                                 break;
                                                             case EBML_ID_GAMMAVALUE:
                                                                 $track_entry[$sub_subelement_idname] = getid3_lib::BigEndian2Float(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_subelement_length));
                                                                 break;
                                                             case EBML_ID_COLOURSPACE:
                                                                 $track_entry[$sub_subelement_idname] = trim(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_subelement_length), "");
                                                                 break;
                                                             default:
                                                                 $this->warnings[] = 'Unhandled track.video element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $sub_subelement_id . '::' . $sub_subelement_idname . ') at ' . $sub_subelement_offset;
                                                                 break;
                                                         }
                                                         $offset = $sub_subelement_end;
                                                     }
                                                     if (isset($track_entry[$this->EBMLidName(EBML_ID_CODECID)]) && $track_entry[$this->EBMLidName(EBML_ID_CODECID)] == 'V_MS/VFW/FOURCC' && isset($track_entry[$this->EBMLidName(EBML_ID_CODECPRIVATE)])) {
                                                         if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio-video.riff.php', __FILE__, false)) {
                                                             $track_entry['codec_private_parsed'] = getid3_riff::ParseBITMAPINFOHEADER($track_entry[$this->EBMLidName(EBML_ID_CODECPRIVATE)]);
                                                         } else {
                                                             $this->warnings[] = 'Unable to parse codec private data [' . basename(__FILE__) . ':' . __LINE__ . '] because cannot include "module.audio-video.riff.php"';
                                                         }
                                                     }
                                                     break;
                                                 case EBML_ID_AUDIO:
                                                     while ($offset < $subelement_end) {
                                                         $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                                         $sub_subelement_offset = $offset;
                                                         $sub_subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                         $sub_subelement_idname = $this->EBMLidName($sub_subelement_id);
                                                         $sub_subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                         $sub_subelement_end = $offset + $sub_subelement_length;
                                                         switch ($sub_subelement_id) {
                                                             case EBML_ID_CHANNELS:
                                                             case EBML_ID_BITDEPTH:
                                                                 $track_entry[$sub_subelement_idname] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_subelement_length));
                                                                 break;
                                                             case EBML_ID_SAMPLINGFREQUENCY:
                                                             case EBML_ID_OUTPUTSAMPLINGFREQUENCY:
                                                                 $track_entry[$sub_subelement_idname] = getid3_lib::BigEndian2Float(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_subelement_length));
                                                                 break;
                                                             case EBML_ID_CHANNELPOSITIONS:
                                                                 $track_entry[$sub_subelement_idname] = trim(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_subelement_length), "");
                                                                 break;
                                                             default:
                                                                 $this->warnings[] = 'Unhandled track.audio element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $sub_subelement_id . '::' . $sub_subelement_idname . ') at ' . $sub_subelement_offset;
                                                                 break;
                                                         }
                                                         $offset = $sub_subelement_end;
                                                     }
                                                     break;
                                                 case EBML_ID_CONTENTENCODINGS:
                                                     while ($offset < $subelement_end) {
                                                         $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                                         $sub_subelement_offset = $offset;
                                                         $sub_subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                         $sub_subelement_idname = $this->EBMLidName($sub_subelement_id);
                                                         $sub_subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                         $sub_subelement_end = $offset + $sub_subelement_length;
                                                         switch ($sub_subelement_id) {
                                                             case EBML_ID_CONTENTENCODING:
                                                                 while ($offset < $sub_subelement_end) {
                                                                     $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                                                     $sub_sub_subelement_offset = $offset;
                                                                     $sub_sub_subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                                     $sub_sub_subelement_idname = $this->EBMLidName($sub_sub_subelement_id);
                                                                     $sub_sub_subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                                     $sub_sub_subelement_end = $offset + $sub_sub_subelement_length;
                                                                     switch ($sub_sub_subelement_id) {
                                                                         case EBML_ID_CONTENTENCODINGORDER:
                                                                         case EBML_ID_CONTENTENCODINGSCOPE:
                                                                         case EBML_ID_CONTENTENCODINGTYPE:
                                                                             $track_entry[$sub_subelement_idname][$sub_sub_subelement_idname] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_sub_subelement_length));
                                                                             break;
                                                                         case EBML_ID_CONTENTCOMPRESSION:
                                                                             while ($offset < $sub_sub_subelement_end) {
                                                                                 $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                                                                 $sub_sub_sub_subelement_offset = $offset;
                                                                                 $sub_sub_sub_subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                                                 $sub_sub_sub_subelement_idname = $this->EBMLidName($sub_sub_subelement_id);
                                                                                 $sub_sub_sub_subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                                                 $sub_sub_sub_subelement_end = $offset + $sub_sub_sub_subelement_length;
                                                                                 switch ($sub_sub_sub_subelement_id) {
                                                                                     case EBML_ID_CONTENTCOMPALGO:
                                                                                         $track_entry[$sub_subelement_idname][$sub_sub_subelement_idname][$sub_sub_sub_subelement_idname] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_sub_sub_subelement_length));
                                                                                         break;
                                                                                     case EBML_ID_CONTENTCOMPSETTINGS:
                                                                                         $track_entry[$sub_subelement_idname][$sub_sub_subelement_idname][$sub_sub_sub_subelement_idname] = substr($EBMLdata, $offset - $EBMLdata_offset, $sub_sub_sub_subelement_length);
                                                                                         break;
                                                                                     default:
                                                                                         $this->warnings[] = 'Unhandled track.contentencodings.contentencoding.contentcompression element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $subelement_id . '::' . $subelement_idname . ' [' . $subelement_length . ' bytes]) at ' . $subelement_offset;
                                                                                         break;
                                                                                 }
                                                                                 $offset = $sub_sub_sub_subelement_end;
                                                                             }
                                                                             break;
                                                                         case EBML_ID_CONTENTENCRYPTION:
                                                                             while ($offset < $sub_sub_subelement_end) {
                                                                                 $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                                                                 $sub_sub_sub_subelement_offset = $offset;
                                                                                 $sub_sub_sub_subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                                                 $sub_sub_sub_subelement_idname = $this->EBMLidName($sub_sub_subelement_id);
                                                                                 $sub_sub_sub_subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                                                 $sub_sub_sub_subelement_end = $offset + $sub_sub_sub_subelement_length;
                                                                                 switch ($sub_sub_sub_subelement_id) {
                                                                                     case EBML_ID_CONTENTENCALGO:
                                                                                     case EBML_ID_CONTENTSIGALGO:
                                                                                     case EBML_ID_CONTENTSIGHASHALGO:
                                                                                         $track_entry[$sub_subelement_idname][$sub_sub_subelement_idname][$sub_sub_sub_subelement_idname] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_sub_sub_subelement_length));
                                                                                         break;
                                                                                     case EBML_ID_CONTENTENCKEYID:
                                                                                     case EBML_ID_CONTENTSIGNATURE:
                                                                                     case EBML_ID_CONTENTSIGKEYID:
                                                                                         $track_entry[$sub_subelement_idname][$sub_sub_subelement_idname][$sub_sub_sub_subelement_idname] = substr($EBMLdata, $offset - $EBMLdata_offset, $sub_sub_sub_subelement_length);
                                                                                         break;
                                                                                     default:
                                                                                         $this->warnings[] = 'Unhandled track.contentencodings.contentencoding.contentcompression element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $subelement_id . '::' . $subelement_idname . ' [' . $subelement_length . ' bytes]) at ' . $subelement_offset;
                                                                                         break;
                                                                                 }
                                                                                 $offset = $sub_sub_sub_subelement_end;
                                                                             }
                                                                             break;
                                                                         default:
                                                                             $this->warnings[] = 'Unhandled track.contentencodings.contentencoding element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $subelement_id . '::' . $subelement_idname . ' [' . $subelement_length . ' bytes]) at ' . $subelement_offset;
                                                                             break;
                                                                     }
                                                                     $offset = $sub_sub_subelement_end;
                                                                 }
                                                                 break;
                                                             default:
                                                                 $this->warnings[] = 'Unhandled track.contentencodings element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $subelement_id . '::' . $subelement_idname . ' [' . $subelement_length . ' bytes]) at ' . $subelement_offset;
                                                                 break;
                                                         }
                                                         $offset = $sub_subelement_end;
                                                     }
                                                     break;
                                                 case EBML_ID_CRC32:
                                                     // probably not useful, ignore
                                                     break;
                                                 default:
                                                     $this->warnings[] = 'Unhandled track element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $subelement_id . '::' . $subelement_idname . ' [' . $subelement_length . ' bytes]) at ' . $subelement_offset;
                                                     break;
                                             }
                                             $offset = $subelement_end;
                                         }
                                         break;
                                     case EBML_ID_CRC32:
                                         // probably not useful, ignore
                                         $offset = $track_entry_endoffset;
                                         break;
                                     default:
                                         $this->warnings[] = 'Unhandled track element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $track_entry['id'] . '::' . $track_entry['id_name'] . ') at ' . $track_entry['offset'];
                                         $offset = $track_entry_endoffset;
                                         break;
                                 }
                                 $info['matroska']['tracks']['tracks'][] = $track_entry;
                             }
                             break;
                         case EBML_ID_INFO:
                             // Contains the position of other level 1 elements
                             $info_entry = array();
                             while ($offset < $element_end) {
                                 $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                 $subelement_offset = $offset;
                                 $subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                 $subelement_idname = $this->EBMLidName($subelement_id);
                                 $subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                 $subelement_end = $offset + $subelement_length;
                                 switch ($subelement_id) {
                                     case EBML_ID_CHAPTERTRANSLATEEDITIONUID:
                                     case EBML_ID_CHAPTERTRANSLATECODEC:
                                     case EBML_ID_TIMECODESCALE:
                                         $info_entry[$subelement_idname] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $subelement_length));
                                         break;
                                     case EBML_ID_DURATION:
                                         $info_entry[$subelement_idname] = getid3_lib::BigEndian2Float(substr($EBMLdata, $offset - $EBMLdata_offset, $subelement_length));
                                         break;
                                     case EBML_ID_DATEUTC:
                                         $info_entry[$subelement_idname] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $subelement_length));
                                         $info_entry[$subelement_idname . '_unix'] = $this->EBMLdate2unix($info_entry[$subelement_idname]);
                                         break;
                                     case EBML_ID_SEGMENTUID:
                                     case EBML_ID_PREVUID:
                                     case EBML_ID_NEXTUID:
                                     case EBML_ID_SEGMENTFAMILY:
                                     case EBML_ID_CHAPTERTRANSLATEID:
                                         $info_entry[$subelement_idname] = trim(substr($EBMLdata, $offset - $EBMLdata_offset, $subelement_length), "");
                                         break;
                                     case EBML_ID_SEGMENTFILENAME:
                                     case EBML_ID_PREVFILENAME:
                                     case EBML_ID_NEXTFILENAME:
                                     case EBML_ID_TITLE:
                                     case EBML_ID_MUXINGAPP:
                                     case EBML_ID_WRITINGAPP:
                                         $info_entry[$subelement_idname] = trim(substr($EBMLdata, $offset - $EBMLdata_offset, $subelement_length), "");
                                         $info['matroska']['comments'][strtolower($subelement_idname)][] = $info_entry[$subelement_idname];
                                         break;
                                     case EBML_ID_CRC32:
                                         // probably not useful, ignore
                                         break;
                                     default:
                                         $this->warnings[] = 'Unhandled info element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $subelement_id . '::' . $subelement_idname . ' [' . $subelement_length . ' bytes]) at ' . $subelement_offset;
                                         break;
                                 }
                                 $offset = $subelement_end;
                             }
                             $info['matroska']['info'][] = $info_entry;
                             break;
                         case EBML_ID_CUES:
                             $cues_entry = array();
                             while ($offset < $element_end) {
                                 $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                 $subelement_offset = $offset;
                                 $subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                 $subelement_idname = $this->EBMLidName($subelement_id);
                                 $subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                 $subelement_end = $offset + $subelement_length;
                                 switch ($subelement_id) {
                                     case EBML_ID_CUEPOINT:
                                         $cuepoint_entry = array();
                                         while ($offset < $subelement_end) {
                                             $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                             $sub_subelement_offset = $offset;
                                             $sub_subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                             $sub_subelement_idname = $this->EBMLidName($sub_subelement_id);
                                             $sub_subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                             $sub_subelement_end = $offset + $sub_subelement_length;
                                             switch ($sub_subelement_id) {
                                                 case EBML_ID_CUETRACKPOSITIONS:
                                                     while ($offset < $sub_subelement_end) {
                                                         $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                                         $sub_sub_subelement_offset = $offset;
                                                         $sub_sub_subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                         $sub_sub_subelement_idname = $this->EBMLidName($sub_sub_subelement_id);
                                                         $sub_sub_subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                         $sub_sub_subelement_end = $offset + $sub_sub_subelement_length;
                                                         switch ($sub_sub_subelement_id) {
                                                             case EBML_ID_CUETRACK:
                                                                 $cuepoint_entry[$sub_sub_subelement_idname] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_sub_subelement_length));
                                                                 break;
                                                             default:
                                                                 $this->warnings[] = 'Unhandled cues.cuepoint.cuetrackpositions element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $sub_sub_subelement_id . '::' . $sub_sub_subelement_idname . ') at ' . $sub_sub_subelement_offset;
                                                                 break;
                                                         }
                                                         $offset = $sub_subelement_end;
                                                     }
                                                     break;
                                                 case EBML_ID_CUETIME:
                                                     $cuepoint_entry[$subelement_idname] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_subelement_length));
                                                     break;
                                                 default:
                                                     $this->warnings[] = 'Unhandled cues.cuepoint element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $sub_subelement_id . '::' . $sub_subelement_idname . ') at ' . $sub_subelement_offset;
                                                     break;
                                             }
                                             $offset = $sub_subelement_end;
                                         }
                                         $cues_entry[] = $cuepoint_entry;
                                         $offset = $sub_subelement_end;
                                         break;
                                     case EBML_ID_CRC32:
                                         // probably not useful, ignore
                                         break;
                                     default:
                                         $this->warnings[] = 'Unhandled cues element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $subelement_id . '::' . $subelement_idname . ' [' . $subelement_length . ' bytes]) at ' . $subelement_offset;
                                         break;
                                 }
                                 $offset = $subelement_end;
                             }
                             $info['matroska']['cues'] = $cues_entry;
                             break;
                         case EBML_ID_TAGS:
                             $tags_entry = array();
                             while ($offset < $element_end) {
                                 $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                 $subelement_offset = $offset;
                                 $subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                 $subelement_idname = $this->EBMLidName($subelement_id);
                                 $subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                 $subelement_end = $offset + $subelement_length;
                                 $tag_entry = array();
                                 switch ($subelement_id) {
                                     case EBML_ID_WRITINGAPP:
                                         $tag_entry[$subelement_idname] = substr($EBMLdata, $offset - $EBMLdata_offset, $subelement_length);
                                         break;
                                     case EBML_ID_TAG:
                                         while ($offset < $subelement_end) {
                                             $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                             $sub_subelement_offset = $offset;
                                             $sub_subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                             $sub_subelement_idname = $this->EBMLidName($sub_subelement_id);
                                             $sub_subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                             $sub_subelement_end = $offset + $sub_subelement_length;
                                             switch ($sub_subelement_id) {
                                                 case EBML_ID_TARGETS:
                                                     $targets_entry = array();
                                                     while ($offset < $sub_subelement_end) {
                                                         $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                                         $sub_sub_subelement_offset = $offset;
                                                         $sub_sub_subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                         $sub_sub_subelement_idname = $this->EBMLidName($sub_sub_subelement_id);
                                                         $sub_sub_subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                         $sub_sub_subelement_end = $offset + $sub_sub_subelement_length;
                                                         switch ($sub_sub_subelement_id) {
                                                             case EBML_ID_TARGETTYPEVALUE:
                                                                 $targets_entry[$sub_sub_subelement_idname] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_sub_subelement_length));
                                                                 $targets_entry[strtolower($sub_sub_subelement_idname) . '_long'] = $this->MatroskaTargetTypeValue($targets_entry[$sub_sub_subelement_idname]);
                                                                 break;
                                                             case EBML_ID_EDITIONUID:
                                                             case EBML_ID_CHAPTERUID:
                                                             case EBML_ID_ATTACHMENTUID:
                                                             case EBML_ID_TAGTRACKUID:
                                                             case EBML_ID_TAGCHAPTERUID:
                                                                 $targets_entry[$sub_sub_subelement_idname] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_sub_subelement_length));
                                                                 break;
                                                             default:
                                                                 $this->warnings[] = 'Unhandled tag.targets element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $sub_sub_subelement_id . '::' . $sub_sub_subelement_idname . ') at ' . $sub_sub_subelement_offset;
                                                                 break;
                                                         }
                                                         $offset = $sub_sub_subelement_end;
                                                     }
                                                     $tag_entry[$sub_subelement_idname][] = $targets_entry;
                                                     break;
                                                 case EBML_ID_SIMPLETAG:
                                                     //$tag_entry[$sub_subelement_idname][] = $simpletag_entry;
                                                     $tag_entry[$sub_subelement_idname][] = $this->Handle_EMBL_ID_SIMPLETAG($offset, $sub_subelement_end);
                                                     break;
                                                 case EBML_ID_TARGETTYPE:
                                                     $tag_entry[$sub_subelement_idname] = substr($EBMLdata, $offset - $EBMLdata_offset, $sub_subelement_length);
                                                     break;
                                                 case EBML_ID_TRACKUID:
                                                     $tag_entry[$sub_subelement_idname] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_subelement_length));
                                                     break;
                                                 default:
                                                     $this->warnings[] = 'Unhandled tags.tag element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $sub_subelement_id . '::' . $sub_subelement_idname . ') at ' . $sub_subelement_offset;
                                                     break;
                                             }
                                             $offset = $sub_subelement_end;
                                         }
                                         $offset = $sub_subelement_end;
                                         break;
                                     case EBML_ID_CRC32:
                                         // probably not useful, ignore
                                         break;
                                     default:
                                         $this->warnings[] = 'Unhandled tags element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $subelement_id . '::' . $subelement_idname . ' [' . $subelement_length . ' bytes]) at ' . $subelement_offset;
                                         break;
                                 }
                                 $tags_entry['tags'][] = $tag_entry;
                                 $offset = $subelement_end;
                             }
                             $info['matroska']['tags'] = $tags_entry['tags'];
                             break;
                         case EBML_ID_ATTACHMENTS:
                             while ($offset < $element_end) {
                                 $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                 $subelement_offset = $offset;
                                 $subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                 $subelement_idname = $this->EBMLidName($subelement_id);
                                 $subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                 $subelement_end = $offset + $subelement_length;
                                 switch ($subelement_id) {
                                     case EBML_ID_ATTACHEDFILE:
                                         $attachedfile_entry = array();
                                         while ($offset < $subelement_end) {
                                             $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                             $sub_subelement_offset = $offset;
                                             $sub_subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                             $sub_subelement_idname = $this->EBMLidName($sub_subelement_id);
                                             $sub_subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                             $sub_subelement_end = $offset + $sub_subelement_length;
                                             switch ($sub_subelement_id) {
                                                 case EBML_ID_FILEDESCRIPTION:
                                                 case EBML_ID_FILENAME:
                                                 case EBML_ID_FILEMIMETYPE:
                                                     $attachedfile_entry[$sub_subelement_idname] = substr($EBMLdata, $offset - $EBMLdata_offset, $sub_subelement_length);
                                                     break;
                                                 case EBML_ID_FILEDATA:
                                                     $attachedfile_entry['data_offset'] = $offset;
                                                     $attachedfile_entry['data_length'] = $sub_subelement_length;
                                                     do {
                                                         if ($this->inline_attachments === false) {
                                                             // skip entirely
                                                             break;
                                                         }
                                                         if ($this->inline_attachments === true) {
                                                             // great
                                                         } elseif (is_int($this->inline_attachments)) {
                                                             if ($this->inline_attachments < $sub_subelement_length) {
                                                                 // too big, skip
                                                                 $this->warnings[] = 'attachment at ' . $sub_subelement_offset . ' is too large to process inline (' . number_format($sub_subelement_length) . ' bytes)';
                                                                 break;
                                                             }
                                                         } elseif (is_string($this->inline_attachments)) {
                                                             $this->inline_attachments = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->inline_attachments), DIRECTORY_SEPARATOR);
                                                             if (!is_dir($this->inline_attachments) || !is_writable($this->inline_attachments)) {
                                                                 // cannot write, skip
                                                                 $this->warnings[] = 'attachment at ' . $sub_subelement_offset . ' cannot be saved to "' . $this->inline_attachments . '" (not writable)';
                                                                 break;
                                                             }
                                                         }
                                                         // if we get this far, must be OK
                                                         $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset, $sub_subelement_length);
                                                         $attachedfile_entry[$sub_subelement_idname] = substr($EBMLdata, $offset - $EBMLdata_offset, $sub_subelement_length);
                                                         if (is_string($this->inline_attachments)) {
                                                             $destination_filename = $this->inline_attachments . DIRECTORY_SEPARATOR . md5($info['filenamepath']) . '_' . $attachedfile_entry['data_offset'];
                                                             if (!file_exists($destination_filename) || is_writable($destination_filename)) {
                                                                 file_put_contents($destination_filename, $attachedfile_entry[$sub_subelement_idname]);
                                                             } else {
                                                                 $this->warnings[] = 'attachment at ' . $sub_subelement_offset . ' cannot be saved to "' . $destination_filename . '" (not writable)';
                                                             }
                                                             $attachedfile_entry[$sub_subelement_idname . '_filename'] = $destination_filename;
                                                             unset($attachedfile_entry[$sub_subelement_idname]);
                                                         }
                                                     } while (false);
                                                     break;
                                                 case EBML_ID_FILEUID:
                                                     $attachedfile_entry[$sub_subelement_idname] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_subelement_length));
                                                     break;
                                                 default:
                                                     $this->warnings[] = 'Unhandled attachment.attachedfile element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $sub_subelement_id . '::' . $sub_subelement_idname . ') at ' . $sub_subelement_offset;
                                                     break;
                                             }
                                             $offset = $sub_subelement_end;
                                         }
                                         if (!empty($attachedfile_entry[$this->EBMLidName(EBML_ID_FILEDATA)]) && !empty($attachedfile_entry[$this->EBMLidName(EBML_ID_FILEMIMETYPE)]) && preg_match('#^image/#i', $attachedfile_entry[$this->EBMLidName(EBML_ID_FILEMIMETYPE)])) {
                                             if ($this->inline_attachments === true || is_int($this->inline_attachments) && $this->inline_attachments >= strlen($attachedfile_entry[$this->EBMLidName(EBML_ID_FILEDATA)])) {
                                                 $attachedfile_entry['data'] = $attachedfile_entry[$this->EBMLidName(EBML_ID_FILEDATA)];
                                                 $attachedfile_entry['image_mime'] = $attachedfile_entry[$this->EBMLidName(EBML_ID_FILEMIMETYPE)];
                                                 $info['matroska']['comments']['picture'][] = array('data' => $attachedfile_entry['data'], 'image_mime' => $attachedfile_entry['image_mime'], 'filename' => !empty($attachedfile_entry[$this->EBMLidName(EBML_ID_FILENAME)]) ? $attachedfile_entry[$this->EBMLidName(EBML_ID_FILENAME)] : '');
                                                 unset($attachedfile_entry[$this->EBMLidName(EBML_ID_FILEDATA)], $attachedfile_entry[$this->EBMLidName(EBML_ID_FILEMIMETYPE)]);
                                             }
                                         }
                                         if (!empty($attachedfile_entry['image_mime']) && preg_match('#^image/#i', $attachedfile_entry['image_mime'])) {
                                             // don't add a second copy of attached images, which are grouped under the standard location [comments][picture]
                                         } else {
                                             $info['matroska']['attachments'][] = $attachedfile_entry;
                                         }
                                         $offset = $sub_subelement_end;
                                         break;
                                     case EBML_ID_CRC32:
                                         // probably not useful, ignore
                                         break;
                                     default:
                                         $this->warnings[] = 'Unhandled tags element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $subelement_id . '::' . $subelement_idname . ' [' . $subelement_length . ' bytes]) at ' . $subelement_offset;
                                         break;
                                 }
                                 $offset = $subelement_end;
                             }
                             break;
                         case EBML_ID_CHAPTERS:
                             // not important to us, contains mostly actual audio/video data, ignore
                             while ($offset < $element_end) {
                                 $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                 $subelement_offset = $offset;
                                 $subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                 $subelement_idname = $this->EBMLidName($subelement_id);
                                 $subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                 $subelement_end = $offset + $subelement_length;
                                 switch ($subelement_id) {
                                     case EBML_ID_EDITIONENTRY:
                                         $editionentry_entry = array();
                                         while ($offset < $subelement_end) {
                                             $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                             $sub_subelement_offset = $offset;
                                             $sub_subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                             $sub_subelement_idname = $this->EBMLidName($sub_subelement_id);
                                             $sub_subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                             $sub_subelement_end = $offset + $sub_subelement_length;
                                             switch ($sub_subelement_id) {
                                                 case EBML_ID_EDITIONUID:
                                                     $editionentry_entry[$sub_subelement_idname] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_subelement_length));
                                                     break;
                                                 case EBML_ID_EDITIONFLAGHIDDEN:
                                                 case EBML_ID_EDITIONFLAGDEFAULT:
                                                 case EBML_ID_EDITIONFLAGORDERED:
                                                     $editionentry_entry[$sub_subelement_idname] = (bool) getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_subelement_length));
                                                     break;
                                                 case EBML_ID_CHAPTERATOM:
                                                     $chapteratom_entry = array();
                                                     while ($offset < $sub_subelement_end) {
                                                         $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                                         $sub_sub_subelement_offset = $offset;
                                                         $sub_sub_subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                         $sub_sub_subelement_idname = $this->EBMLidName($sub_sub_subelement_id);
                                                         $sub_sub_subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                         $sub_sub_subelement_end = $offset + $sub_sub_subelement_length;
                                                         switch ($sub_sub_subelement_id) {
                                                             case EBML_ID_CHAPTERSEGMENTUID:
                                                             case EBML_ID_CHAPTERSEGMENTEDITIONUID:
                                                                 $chapteratom_entry[$sub_sub_subelement_idname] = substr($EBMLdata, $offset - $EBMLdata_offset, $sub_sub_subelement_length);
                                                                 break;
                                                             case EBML_ID_CHAPTERFLAGENABLED:
                                                             case EBML_ID_CHAPTERFLAGHIDDEN:
                                                                 $chapteratom_entry[$sub_sub_subelement_idname] = (bool) getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_sub_subelement_length));
                                                                 break;
                                                             case EBML_ID_CHAPTERUID:
                                                             case EBML_ID_CHAPTERTIMESTART:
                                                             case EBML_ID_CHAPTERTIMEEND:
                                                                 $chapteratom_entry[$sub_sub_subelement_idname] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_sub_subelement_length));
                                                                 break;
                                                             case EBML_ID_CHAPTERTRACK:
                                                                 $chaptertrack_entry = array();
                                                                 while ($offset < $sub_sub_subelement_end) {
                                                                     $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                                                     $sub_sub_sub_subelement_offset = $offset;
                                                                     $sub_sub_sub_subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                                     $sub_sub_sub_subelement_idname = $this->EBMLidName($sub_sub_subelement_id);
                                                                     $sub_sub_sub_subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                                     $sub_sub_sub_subelement_end = $offset + $sub_sub_sub_subelement_length;
                                                                     switch ($sub_sub_sub_subelement_id) {
                                                                         case EBML_ID_CHAPTERTRACKNUMBER:
                                                                             $chaptertrack_entry[$sub_sub_sub_subelement_idname] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_sub_sub_subelement_length));
                                                                             break;
                                                                         default:
                                                                             $this->warnings[] = 'Unhandled chapters.editionentry.chapteratom.chaptertrack element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $sub_sub_sub_subelement_id . '::' . $sub_sub_sub_subelement_idname . ') at ' . $sub_sub_sub_subelement_offset;
                                                                             break;
                                                                     }
                                                                     $offset = $sub_sub_sub_subelement_end;
                                                                 }
                                                                 $chapteratom_entry[$sub_sub_subelement_idname][] = $chaptertrack_entry;
                                                                 break;
                                                             case EBML_ID_CHAPTERDISPLAY:
                                                                 $chapterdisplay_entry = array();
                                                                 while ($offset < $sub_sub_subelement_end) {
                                                                     $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                                                     $sub_sub_sub_subelement_offset = $offset;
                                                                     $sub_sub_sub_subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                                     $sub_sub_sub_subelement_idname = $this->EBMLidName($sub_sub_sub_subelement_id);
                                                                     $sub_sub_sub_subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                                     $sub_sub_sub_subelement_end = $offset + $sub_sub_sub_subelement_length;
                                                                     switch ($sub_sub_sub_subelement_id) {
                                                                         case EBML_ID_CHAPSTRING:
                                                                         case EBML_ID_CHAPLANGUAGE:
                                                                         case EBML_ID_CHAPCOUNTRY:
                                                                             $chapterdisplay_entry[$sub_sub_sub_subelement_idname] = substr($EBMLdata, $offset - $EBMLdata_offset, $sub_sub_sub_subelement_length);
                                                                             break;
                                                                         default:
                                                                             $this->warnings[] = 'Unhandled chapters.editionentry.chapteratom.chapterdisplay element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $sub_sub_sub_subelement_id . '::' . $sub_sub_sub_subelement_idname . ') at ' . $sub_sub_sub_subelement_offset;
                                                                             break;
                                                                     }
                                                                     $offset = $sub_sub_sub_subelement_end;
                                                                 }
                                                                 $chapteratom_entry[$sub_sub_subelement_idname][] = $chapterdisplay_entry;
                                                                 break;
                                                             default:
                                                                 $this->warnings[] = 'Unhandled chapters.editionentry.chapteratom element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $sub_sub_subelement_id . '::' . $sub_sub_subelement_idname . ') at ' . $sub_sub_subelement_offset;
                                                                 break;
                                                         }
                                                         $offset = $sub_sub_subelement_end;
                                                     }
                                                     $editionentry_entry[$sub_subelement_idname][] = $chapteratom_entry;
                                                     break;
                                                 default:
                                                     $this->warnings[] = 'Unhandled chapters.editionentry element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $sub_subelement_id . '::' . $sub_subelement_idname . ') at ' . $sub_subelement_offset;
                                                     break;
                                             }
                                             $offset = $sub_subelement_end;
                                         }
                                         $info['matroska']['chapters'][] = $editionentry_entry;
                                         $offset = $sub_subelement_end;
                                         break;
                                     default:
                                         $this->warnings[] = 'Unhandled chapters element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $subelement_id . '::' . $subelement_idname . ' [' . $subelement_length . ' bytes]) at ' . $subelement_offset;
                                         break;
                                 }
                                 $offset = $subelement_end;
                             }
                             break;
                         case EBML_ID_VOID:
                             // padding, ignore
                             $void_entry = array();
                             $void_entry['offset'] = $offset;
                             $info['matroska']['void'][] = $void_entry;
                             break;
                         case EBML_ID_CLUSTER:
                             // not important to us, contains mostly actual audio/video data, ignore
                             $cluster_entry = array();
                             while ($offset < $element_end) {
                                 $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                 $subelement_offset = $offset;
                                 $subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                 $subelement_idname = $this->EBMLidName($subelement_id);
                                 $subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                 $subelement_end = $offset + $subelement_length;
                                 switch ($subelement_id) {
                                     case EBML_ID_CLUSTERTIMECODE:
                                     case EBML_ID_CLUSTERPOSITION:
                                     case EBML_ID_CLUSTERPREVSIZE:
                                         $cluster_entry[$subelement_idname] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $subelement_length));
                                         break;
                                     case EBML_ID_CLUSTERSILENTTRACKS:
                                         $cluster_silent_tracks = array();
                                         while ($offset < $subelement_end) {
                                             $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                             $sub_subelement_offset = $offset;
                                             $sub_subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                             $sub_subelement_idname = $this->EBMLidName($sub_subelement_id);
                                             $sub_subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                             $sub_subelement_end = $offset + $sub_subelement_length;
                                             switch ($sub_subelement_id) {
                                                 case EBML_ID_CLUSTERSILENTTRACKNUMBER:
                                                     $cluster_silent_tracks[] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_subelement_length));
                                                     break;
                                                 default:
                                                     $this->warnings[] = 'Unhandled clusters.silenttracks element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $sub_subelement_id . '::' . $sub_subelement_idname . ') at ' . $sub_subelement_offset;
                                                     break;
                                             }
                                             $offset = $sub_subelement_end;
                                         }
                                         $cluster_entry[$subelement_idname][] = $cluster_silent_tracks;
                                         $offset = $sub_subelement_end;
                                         break;
                                     case EBML_ID_CLUSTERBLOCKGROUP:
                                         $cluster_block_group = array('offset' => $offset);
                                         while ($offset < $subelement_end) {
                                             $this->EnsureBufferHasEnoughData($EBMLdata, $offset, $EBMLdata_offset);
                                             $sub_subelement_offset = $offset;
                                             $sub_subelement_id = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                             $sub_subelement_idname = $this->EBMLidName($sub_subelement_id);
                                             $sub_subelement_length = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                             $sub_subelement_end = $offset + $sub_subelement_length;
                                             switch ($sub_subelement_id) {
                                                 case EBML_ID_CLUSTERBLOCK:
                                                     $cluster_block_data = array();
                                                     $cluster_block_data['tracknumber'] = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                                     $cluster_block_data['timecode'] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset, 2));
                                                     $offset += 2;
                                                     // unsure whether this is 1 octect or 2 octets? (http://matroska.org/technical/specs/index.html#block_structure)
                                                     $cluster_block_data['flags_raw'] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset, 1));
                                                     $offset += 1;
                                                     //$cluster_block_data['flags']['reserved1'] =      (($cluster_block_data['flags_raw'] & 0xF0) >> 4);
                                                     $cluster_block_data['flags']['invisible'] = (bool) (($cluster_block_data['flags_raw'] & 0x8) >> 3);
                                                     $cluster_block_data['flags']['lacing'] = ($cluster_block_data['flags_raw'] & 0x6) >> 1;
                                                     //$cluster_block_data['flags']['reserved2'] =      (($cluster_block_data['flags_raw'] & 0x01) >> 0);
                                                     $cluster_block_data['flags']['lacing_type'] = $this->MatroskaBlockLacingType($cluster_block_data['flags']['lacing']);
                                                     if ($cluster_block_data['flags']['lacing'] != 0) {
                                                         $cluster_block_data['lace_frames'] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset, 1));
                                                         // Number of frames in the lace-1 (uint8)
                                                         $offset += 1;
                                                         if ($cluster_block_data['flags']['lacing'] != 2) {
                                                             $cluster_block_data['lace_frames'] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset, 1));
                                                             // Lace-coded size of each frame of the lace, except for the last one (multiple uint8). *This is not used with Fixed-size lacing as it is calculated automatically from (total size of lace) / (number of frames in lace).
                                                             $offset += 1;
                                                         }
                                                     }
                                                     if (!isset($info['matroska']['track_data_offsets'][$cluster_block_data['tracknumber']])) {
                                                         $info['matroska']['track_data_offsets'][$cluster_block_data['tracknumber']]['offset'] = $offset;
                                                         $info['matroska']['track_data_offsets'][$cluster_block_data['tracknumber']]['length'] = $subelement_length;
                                                     }
                                                     $cluster_block_group[$sub_subelement_idname] = $cluster_block_data;
                                                     break;
                                                 case EBML_ID_CLUSTERREFERENCEPRIORITY:
                                                     // unsigned-int
                                                 // unsigned-int
                                                 case EBML_ID_CLUSTERBLOCKDURATION:
                                                     // unsigned-int
                                                     $cluster_block_group[$sub_subelement_idname] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_subelement_length));
                                                     break;
                                                 case EBML_ID_CLUSTERREFERENCEBLOCK:
                                                     // signed-int
                                                     $cluster_block_group[$sub_subelement_idname] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset - $EBMLdata_offset, $sub_subelement_length), false, true);
                                                     break;
                                                 default:
                                                     $this->warnings[] = 'Unhandled clusters.blockgroup element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $sub_subelement_id . '::' . $sub_subelement_idname . ') at ' . $sub_subelement_offset;
                                                     break;
                                             }
                                             $offset = $sub_subelement_end;
                                         }
                                         $cluster_entry[$subelement_idname][] = $cluster_block_group;
                                         $offset = $sub_subelement_end;
                                         break;
                                     case EBML_ID_CLUSTERSIMPLEBLOCK:
                                         // http://www.matroska.org/technical/specs/index.html#simpleblock_structure
                                         $cluster_block_data = array();
                                         $cluster_block_data['tracknumber'] = $this->readEBMLint($EBMLdata, $offset, $EBMLdata_offset);
                                         $cluster_block_data['timecode'] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset, 2));
                                         $offset += 2;
                                         $cluster_block_data['flags_raw'] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset, 1));
                                         $offset += 1;
                                         $cluster_block_data['flags']['keyframe'] = ($cluster_block_data['flags_raw'] & 0x80) >> 7;
                                         $cluster_block_data['flags']['reserved1'] = ($cluster_block_data['flags_raw'] & 0x70) >> 4;
                                         $cluster_block_data['flags']['invisible'] = ($cluster_block_data['flags_raw'] & 0x8) >> 3;
                                         $cluster_block_data['flags']['lacing'] = ($cluster_block_data['flags_raw'] & 0x6) >> 1;
                                         // 00=no lacing; 01=Xiph lacing; 11=EBML lacing; 10=fixed-size lacing
                                         $cluster_block_data['flags']['discardable'] = $cluster_block_data['flags_raw'] & 0x1;
                                         if ($cluster_block_data['flags']['lacing'] > 0) {
                                             $cluster_block_data['lace_frames'] = 1 + getid3_lib::BigEndian2Int(substr($EBMLdata, $offset, 1));
                                             $offset += 1;
                                             if ($cluster_block_data['flags']['lacing'] != 0x2) {
                                                 // *This is not used with Fixed-size lacing as it is calculated automatically from (total size of lace) / (number of frames in lace).
                                                 $cluster_block_data['lace_frame_size'] = getid3_lib::BigEndian2Int(substr($EBMLdata, $offset, 1));
                                                 $offset += 1;
                                             }
                                         }
                                         if (!isset($info['matroska']['track_data_offsets'][$cluster_block_data['tracknumber']])) {
                                             $info['matroska']['track_data_offsets'][$cluster_block_data['tracknumber']]['offset'] = $offset;
                                             $info['matroska']['track_data_offsets'][$cluster_block_data['tracknumber']]['length'] = $subelement_length;
                                         }
                                         $cluster_block_group[$sub_subelement_idname] = $cluster_block_data;
                                         break;
                                     default:
                                         $this->warnings[] = 'Unhandled cluster element [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $subelement_id . '::' . $subelement_idname . ' [' . $subelement_length . ' bytes]) at ' . $subelement_offset;
                                         break;
                                 }
                                 $offset = $subelement_end;
                             }
                             $info['matroska']['cluster'][] = $cluster_entry;
                             // check to see if all the data we need exists already, if so, break out of the loop
                             if (isset($info['matroska']['info']) && is_array($info['matroska']['info'])) {
                                 if (isset($info['matroska']['tracks']['tracks']) && is_array($info['matroska']['tracks']['tracks'])) {
                                     break 2;
                                 }
                             }
                             break;
                         default:
                             if ($element_data['id_name'] == dechex($element_data['id'])) {
                                 $info['error'][] = 'Unhandled segment [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $element_data['id'] . ') at ' . $element_data_offset;
                             } else {
                                 $this->warnings[] = 'Unhandled segment [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $element_data['id'] . '::' . $element_data['id_name'] . ') at ' . $element_data['offset'];
                             }
                             break;
                     }
                     $offset = $element_end;
                 }
                 break;
             default:
                 $info['error'][] = 'Unhandled chunk [' . basename(__FILE__) . ':' . __LINE__ . '] (' . $top_element_id . ') at ' . $offset;
                 break;
         }
         $offset = $top_element_endoffset;
     }
     if (isset($info['matroska']['info']) && is_array($info['matroska']['info'])) {
         foreach ($info['matroska']['info'] as $key => $infoarray) {
             if (isset($infoarray['Duration'])) {
                 // TimecodeScale is how many nanoseconds each Duration unit is
                 $info['playtime_seconds'] = $infoarray['Duration'] * ((isset($infoarray['TimecodeScale']) ? $infoarray['TimecodeScale'] : 1000000) / 1000000000);
                 break;
             }
         }
     }
     if (isset($info['matroska']['tags']) && is_array($info['matroska']['tags'])) {
         foreach ($info['matroska']['tags'] as $key => $infoarray) {
             $this->ExtractCommentsSimpleTag($infoarray);
         }
     }
     if (isset($info['matroska']['tracks']['tracks']) && is_array($info['matroska']['tracks']['tracks'])) {
         foreach ($info['matroska']['tracks']['tracks'] as $key => $trackarray) {
             $track_info = array();
             if (isset($trackarray['FlagDefault'])) {
                 $track_info['default'] = $trackarray['FlagDefault'];
             }
             switch (isset($trackarray['TrackType']) ? $trackarray['TrackType'] : '') {
                 case 1:
                     // Video
                     if (!empty($trackarray['PixelWidth'])) {
                         $track_info['resolution_x'] = $trackarray['PixelWidth'];
                     }
                     if (!empty($trackarray['PixelHeight'])) {
                         $track_info['resolution_y'] = $trackarray['PixelHeight'];
                     }
                     if (!empty($trackarray['DisplayWidth'])) {
                         $track_info['display_x'] = $trackarray['DisplayWidth'];
                     }
                     if (!empty($trackarray['DisplayHeight'])) {
                         $track_info['display_y'] = $trackarray['DisplayHeight'];
                     }
                     if (!empty($trackarray['DefaultDuration'])) {
                         $track_info['frame_rate'] = round(1000000000 / $trackarray['DefaultDuration'], 3);
                     }
                     if (!empty($trackarray['CodecID'])) {
                         $track_info['dataformat'] = $this->MatroskaCodecIDtoCommonName($trackarray['CodecID']);
                     }
                     if (!empty($trackarray['codec_private_parsed']['fourcc'])) {
                         $track_info['fourcc'] = $trackarray['codec_private_parsed']['fourcc'];
                     }
                     $info['video']['streams'][] = $track_info;
                     if (isset($track_info['resolution_x']) && empty($info['video']['resolution_x'])) {
                         foreach ($track_info as $key => $value) {
                             $info['video'][$key] = $value;
                         }
                     }
                     break;
                 case 2:
                     // Audio
                     if (!empty($trackarray['CodecID'])) {
                         $track_info['dataformat'] = $this->MatroskaCodecIDtoCommonName($trackarray['CodecID']);
                     }
                     if (!empty($trackarray['SamplingFrequency'])) {
                         $track_info['sample_rate'] = $trackarray['SamplingFrequency'];
                     }
                     if (!empty($trackarray['Channels'])) {
                         $track_info['channels'] = $trackarray['Channels'];
                     }
                     if (!empty($trackarray['BitDepth'])) {
                         $track_info['bits_per_sample'] = $trackarray['BitDepth'];
                     }
                     if (!empty($trackarray['Language'])) {
                         $track_info['language'] = $trackarray['Language'];
                     }
                     switch (isset($trackarray[$this->EBMLidName(EBML_ID_CODECID)]) ? $trackarray[$this->EBMLidName(EBML_ID_CODECID)] : '') {
                         case 'A_PCM/INT/LIT':
                         case 'A_PCM/INT/BIG':
                             $track_info['bitrate'] = $trackarray['SamplingFrequency'] * $trackarray['Channels'] * $trackarray['BitDepth'];
                             break;
                         case 'A_AC3':
                             if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.ac3.php', __FILE__, false)) {
                                 if (isset($info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['offset'])) {
                                     $getid3_temp = new getID3();
                                     $getid3_temp->openfile($this->getid3->filename);
                                     $getid3_temp->info['avdataoffset'] = $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['offset'];
                                     $getid3_ac3 = new getid3_ac3($getid3_temp);
                                     $getid3_ac3->Analyze();
                                     unset($getid3_temp->info['ac3']['GETID3_VERSION']);
                                     $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info['ac3'];
                                     if (!empty($getid3_temp->info['error'])) {
                                         foreach ($getid3_temp->info['error'] as $newerror) {
                                             $this->warnings[] = 'getid3_ac3() says: [' . $newerror . ']';
                                         }
                                     }
                                     if (!empty($getid3_temp->info['warning'])) {
                                         foreach ($getid3_temp->info['warning'] as $newerror) {
                                             $this->warnings[] = 'getid3_ac3() says: [' . $newerror . ']';
                                         }
                                     }
                                     if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
                                         foreach ($getid3_temp->info['audio'] as $key => $value) {
                                             $track_info[$key] = $value;
                                         }
                                     }
                                     unset($getid3_temp, $getid3_ac3);
                                 } else {
                                     $this->warnings[] = 'Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because $info[matroska][track_data_offsets][' . $trackarray['TrackNumber'] . '][offset] not set';
                                 }
                             } else {
                                 $this->warnings[] = 'Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because cannot include "module.audio.ac3.php"';
                             }
                             break;
                         case 'A_DTS':
                             $dts_offset = $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['offset'];
                             // this is a NASTY hack, but sometimes audio data is off by a byte or two and not sure why, email info@getid3.org if you can explain better
                             fseek($this->getid3->fp, $dts_offset, SEEK_SET);
                             $magic_test = fread($this->getid3->fp, 8);
                             for ($i = 0; $i < 4; $i++) {
                                 // look to see if DTS "magic" is here, if so adjust offset by that many bytes
                                 if (substr($magic_test, $i, 4) == "þ€") {
                                     $dts_offset += $i;
                                     break;
                                 }
                             }
                             if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.dts.php', __FILE__, false)) {
                                 $getid3_temp = new getID3();
                                 $getid3_temp->openfile($this->getid3->filename);
                                 $getid3_temp->info['avdataoffset'] = $dts_offset;
                                 $getid3_dts = new getid3_dts($getid3_temp);
                                 $getid3_dts->Analyze();
                                 unset($getid3_temp->info['dts']['GETID3_VERSION']);
                                 $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info['dts'];
                                 if (!empty($getid3_temp->info['error'])) {
                                     foreach ($getid3_temp->info['error'] as $newerror) {
                                         $this->warnings[] = 'getid3_dts() says: [' . $newerror . ']';
                                     }
                                 }
                                 if (!empty($getid3_temp->info['warning'])) {
                                     foreach ($getid3_temp->info['warning'] as $newerror) {
                                         $this->warnings[] = 'getid3_dts() says: [' . $newerror . ']';
                                     }
                                 }
                                 if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
                                     foreach ($getid3_temp->info['audio'] as $key => $value) {
                                         $track_info[$key] = $value;
                                     }
                                 }
                                 unset($getid3_temp, $getid3_dts);
                             } else {
                                 $this->warnings[] = 'Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because cannot include "module.audio.dts.php"';
                             }
                             break;
                         case 'A_AAC':
                             $this->warnings[] = 'This version of getID3() [v' . $this->getid3->version() . '] has problems parsing AAC audio in Matroska containers [' . basename(__FILE__) . ':' . __LINE__ . ']';
                             if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.aac.php', __FILE__, false)) {
                                 $getid3_temp = new getID3();
                                 $getid3_temp->openfile($this->getid3->filename);
                                 $getid3_temp->info['avdataoffset'] = $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['offset'];
                                 $getid3_aac = new getid3_aac($getid3_temp);
                                 $getid3_aac->Analyze();
                                 unset($getid3_temp->info['aac']['GETID3_VERSION']);
                                 if (!empty($getid3_temp->info['audio']['dataformat'])) {
                                     $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info['aac'];
                                     if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
                                         foreach ($getid3_temp->info['audio'] as $key => $value) {
                                             $track_info[$key] = $value;
                                         }
                                     }
                                 } else {
                                     $this->warnings[] = 'Failed to parse ' . $trackarray[$this->EBMLidName(EBML_ID_CODECID)] . ' audio data [' . basename(__FILE__) . ':' . __LINE__ . ']';
                                 }
                                 unset($getid3_temp, $getid3_aac);
                             } else {
                                 $this->warnings[] = 'Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because cannot include "module.audio.aac.php"';
                             }
                             break;
                         case 'A_MPEG/L3':
                             if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.mp3.php', __FILE__, false)) {
                                 $getid3_temp = new getID3();
                                 $getid3_temp->openfile($this->getid3->filename);
                                 $getid3_temp->info['avdataoffset'] = $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['offset'];
                                 $getid3_temp->info['avdataend'] = $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['offset'] + $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['length'];
                                 $getid3_mp3 = new getid3_mp3($getid3_temp);
                                 $getid3_mp3->allow_bruteforce = true;
                                 $getid3_mp3->Analyze();
                                 if (!empty($getid3_temp->info['mpeg'])) {
                                     unset($getid3_temp->info['mpeg']['GETID3_VERSION']);
                                     $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info['mpeg'];
                                     if (!empty($getid3_temp->info['error'])) {
                                         foreach ($getid3_temp->info['error'] as $newerror) {
                                             $this->warnings[] = 'getid3_mp3() says: [' . $newerror . ']';
                                         }
                                     }
                                     if (!empty($getid3_temp->info['warning'])) {
                                         foreach ($getid3_temp->info['warning'] as $newerror) {
                                             $this->warnings[] = 'getid3_mp3() says: [' . $newerror . ']';
                                         }
                                     }
                                     if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
                                         foreach ($getid3_temp->info['audio'] as $key => $value) {
                                             $track_info[$key] = $value;
                                         }
                                     }
                                 } else {
                                     $this->warnings[] = 'Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because getid3_mp3::Analyze failed at offset ' . $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['offset'];
                                 }
                                 unset($getid3_temp, $getid3_mp3);
                             } else {
                                 $this->warnings[] = 'Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because cannot include "module.audio.mp3.php"';
                             }
                             break;
                         case 'A_VORBIS':
                             if (isset($trackarray['CodecPrivate'])) {
                                 // this is a NASTY hack, email info@getid3.org if you have a better idea how to get this info out
                                 $found_vorbis = false;
                                 for ($vorbis_offset = 1; $vorbis_offset < 16; $vorbis_offset++) {
                                     if (substr($trackarray['CodecPrivate'], $vorbis_offset, 6) == 'vorbis') {
                                         $vorbis_offset--;
                                         $found_vorbis = true;
                                         break;
                                     }
                                 }
                                 if ($found_vorbis) {
                                     if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'module.audio.ogg.php', __FILE__, false)) {
                                         $oggpageinfo['page_seqno'] = 0;
                                         $getid3_temp = new getID3();
                                         $getid3_temp->openfile($this->getid3->filename);
                                         $getid3_ogg = new getid3_ogg($getid3_temp);
                                         $getid3_ogg->ParseVorbisPageHeader($trackarray['CodecPrivate'], $vorbis_offset, $oggpageinfo);
                                         $vorbis_fileinfo = $getid3_temp->info;
                                         unset($getid3_temp, $getid3_ogg);
                                         if (isset($vorbis_fileinfo['audio'])) {
                                             $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']]['audio'] = $vorbis_fileinfo['audio'];
                                         }
                                         if (isset($vorbis_fileinfo['ogg'])) {
                                             $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']]['ogg'] = $vorbis_fileinfo['ogg'];
                                         }
                                         if (!empty($vorbis_fileinfo['error'])) {
                                             foreach ($vorbis_fileinfo['error'] as $newerror) {
                                                 $this->warnings[] = 'getid3_ogg() says: [' . $newerror . ']';
                                             }
                                         }
                                         if (!empty($vorbis_fileinfo['warning'])) {
                                             foreach ($vorbis_fileinfo['warning'] as $newerror) {
                                                 $this->warnings[] = 'getid3_ogg() says: [' . $newerror . ']';
                                             }
                                         }
                                         if (isset($vorbis_fileinfo['audio']) && is_array($vorbis_fileinfo['audio'])) {
                                             foreach ($vorbis_fileinfo['audio'] as $key => $value) {
                                                 $track_info[$key] = $value;
                                             }
                                         }
                                         if (!empty($vorbis_fileinfo['ogg']['bitrate_average'])) {
                                             $track_info['bitrate'] = $vorbis_fileinfo['ogg']['bitrate_average'];
                                         } elseif (!empty($vorbis_fileinfo['ogg']['bitrate_nominal'])) {
                                             $track_info['bitrate'] = $vorbis_fileinfo['ogg']['bitrate_nominal'];
                                         }
                                         unset($vorbis_fileinfo);
                                         unset($oggpageinfo);
                                     } else {
                                         $this->warnings[] = 'Unable to parse audio data [' . basename(__FILE__) . ':' . __LINE__ . '] because cannot include "module.audio.ogg.php"';
                                     }
                                 } else {
                                 }
                             } else {
                             }
                             break;
                         default:
                             $this->warnings[] = 'Unhandled audio type "' . (isset($trackarray[$this->EBMLidName(EBML_ID_CODECID)]) ? $trackarray[$this->EBMLidName(EBML_ID_CODECID)] : '') . '"';
                             break;
                     }
                     $info['audio']['streams'][] = $track_info;
                     if (isset($track_info['dataformat']) && empty($info['audio']['dataformat'])) {
                         foreach ($track_info as $key => $value) {
                             $info['audio'][$key] = $value;
                         }
                     }
                     break;
                 default:
                     // ignore, do nothing
                     break;
             }
         }
     }
     if ($this->hide_clusters) {
         // too much data returned that is usually not useful
         if (isset($info['matroska']['segments']) && is_array($info['matroska']['segments'])) {
             foreach ($info['matroska']['segments'] as $key => $segmentsarray) {
                 if ($segmentsarray['id'] == EBML_ID_CLUSTER) {
                     unset($info['matroska']['segments'][$key]);
                 }
             }
         }
         if (isset($info['matroska']['seek']) && is_array($info['matroska']['seek'])) {
             foreach ($info['matroska']['seek'] as $key => $seekarray) {
                 if ($seekarray['target_id'] == EBML_ID_CLUSTER) {
                     unset($info['matroska']['seek'][$key]);
                 }
             }
         }
         //unset($info['matroska']['cluster']);
         //unset($info['matroska']['track_data_offsets']);
     }
     if (!empty($info['video']['streams'])) {
         $info['mime_type'] = 'video/x-matroska';
     } elseif (!empty($info['audio']['streams'])) {
         $info['mime_type'] = 'audio/x-matroska';
     } elseif (isset($info['mime_type'])) {
         unset($info['mime_type']);
     }
     foreach ($this->warnings as $key => $value) {
         $info['warning'][] = $value;
     }
     return true;
 }
Beispiel #29
-1
 /**
  * Get file mime type
  * 
  * @param string $filename The file name 
  * 
  * @return string The MIME type
  */
 public function getMime($filename)
 {
     require_once SRPATH_LIBRARY . '/media/getid3/getid3.php';
     // Initialize getID3 engine
     $getID3 = new getID3();
     $determinedMimeType = '';
     if ($fp = fopen($filename, 'rb')) {
         $thisFileInfo = array('avdataoffset' => 0, 'avdataend' => 0);
         getid3_lib::IncludeDependency(SRPATH_LIBRARY . '/media/getid3/module.tag.id3v2.php', __FILE__, true);
         $tag = new getid3_id3v2($fp, $thisFileInfo);
         fseek($fp, $thisFileInfo['avdataoffset'], SEEK_SET);
         $formattest = fread($fp, 16);
         // 16 bytes is sufficient for any format except ISO CD-image
         fclose($fp);
         $determinedFormatInfo = $getID3->GetFileFormat($formattest);
         $determinedMimeType = $determinedFormatInfo['mime_type'];
     }
     return $determinedMimeType;
 }
Beispiel #30
-2
function SynchronizeAllTags($filename, $synchronizefrom = 'all', $synchronizeto = 'A12', &$errors)
{
    global $getID3;
    set_time_limit(30);
    $ThisFileInfo = $getID3->analyze($filename);
    getid3_lib::CopyTagsToComments($ThisFileInfo);
    if ($synchronizefrom == 'all') {
        $SourceArray = !empty($ThisFileInfo['comments']) ? $ThisFileInfo['comments'] : array();
    } elseif (!empty($ThisFileInfo['tags'][$synchronizefrom])) {
        $SourceArray = !empty($ThisFileInfo['tags'][$synchronizefrom]) ? $ThisFileInfo['tags'][$synchronizefrom] : array();
    } else {
        die('ERROR: $ThisFileInfo[tags][' . $synchronizefrom . '] does not exist');
    }
    $SQLquery = 'DELETE FROM `' . mysql_real_escape_string(GETID3_DB_TABLE) . '`';
    $SQLquery .= ' WHERE (`filename` = "' . mysql_real_escape_string($filename) . '")';
    mysql_query_safe($SQLquery);
    $TagFormatsToWrite = array();
    if (strpos($synchronizeto, '2') !== false && $synchronizefrom != 'id3v2') {
        $TagFormatsToWrite[] = 'id3v2.3';
    }
    if (strpos($synchronizeto, 'A') !== false && $synchronizefrom != 'ape') {
        $TagFormatsToWrite[] = 'ape';
    }
    if (strpos($synchronizeto, 'L') !== false && $synchronizefrom != 'lyrics3') {
        $TagFormatsToWrite[] = 'lyrics3';
    }
    if (strpos($synchronizeto, '1') !== false && $synchronizefrom != 'id3v1') {
        $TagFormatsToWrite[] = 'id3v1';
    }
    getid3_lib::IncludeDependency(GETID3_INCLUDEPATH . 'write.php', __FILE__, true);
    $tagwriter = new getid3_writetags();
    $tagwriter->filename = $filename;
    $tagwriter->tagformats = $TagFormatsToWrite;
    $tagwriter->overwrite_tags = true;
    $tagwriter->tag_encoding = $getID3->encoding;
    $tagwriter->tag_data = $SourceArray;
    if ($tagwriter->WriteTags()) {
        $errors = $tagwriter->errors;
        return true;
    }
    $errors = $tagwriter->errors;
    return false;
}