Proper TXXX tag handling
TXXX consists of description and value. Descriptions should be unique, but rarely are. This now parses them into TXXX:<description> and turns it into an array if multiple tags are found. Signed-off-by: Markus Birth <markus@birth-online.de>
This commit is contained in:
parent
d6977ef4dc
commit
4de63bd94b
@ -29,7 +29,8 @@ use \RuntimeException;
|
||||
* * {@link https://multimedia.cx/mp3extensions.txt Descripion of VBR header "Xing"}
|
||||
* * {@link http://gabriel.mp3-tech.org/mp3infotag.html Xing, Info and Lame tags specifications}
|
||||
*/
|
||||
class Mp3Info {
|
||||
class Mp3Info
|
||||
{
|
||||
const TAG1_SYNC = 'TAG';
|
||||
const TAG2_SYNC = 'ID3';
|
||||
const VBR_SYNC = 'Xing';
|
||||
@ -774,7 +775,6 @@ class Mp3Info {
|
||||
case 'TALB': # Album/Movie/Show title
|
||||
case 'TCON': # Content type
|
||||
case 'TYER': # Year
|
||||
case 'TXXX': # User defined text information frame
|
||||
case 'TRCK': # Track number/Position in set
|
||||
case 'TIT2': # Title/songname/content description
|
||||
case 'TPE1': # Lead performer(s)/Soloist(s)
|
||||
@ -814,6 +814,24 @@ class Mp3Info {
|
||||
$this->tags2[$frame_id] = $this->handleTextFrame($frame_size, $this->fileObj->getBytes($frame_size));
|
||||
break;
|
||||
|
||||
case 'TXXX': # User defined text information frame
|
||||
$dataEnd = $this->fileObj->getFilePos() + $frame_size;
|
||||
$encoding = ord($this->fileObj->getBytes(1));
|
||||
$description_raw = $this->readTextUntilNull($dataEnd);
|
||||
$description = $this->_getUtf8Text($encoding, $description_raw);
|
||||
$value = $this->fileObj->getBytes($dataEnd - $this->fileObj->getFilePos());
|
||||
$tagName = $frame_id . ':' . $description;
|
||||
if (key_exists($tagName, $this->tags2)) {
|
||||
// this should never happen! TXXX-description must be unique.
|
||||
if (!is_array($this->tags2[$tagName])) {
|
||||
$this->tags2[$tagName] = array($this->tags2[$tagName]);
|
||||
}
|
||||
$this->tags2[$tagName][] = $value;
|
||||
} else {
|
||||
$this->tags2[$tagName] = $value;
|
||||
}
|
||||
break;
|
||||
|
||||
################# Text information frames
|
||||
|
||||
################# URL link frames
|
||||
@ -936,6 +954,38 @@ class Mp3Info {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts text encoding according to ID3 indicator
|
||||
*
|
||||
* @param int $encoding Encoding ID from ID3 frame
|
||||
* @param string $rawText Raw text from ID3 frame
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function _getUtf8Text(int $encoding, string|null $rawText): string
|
||||
{
|
||||
if (is_null($rawText)) {
|
||||
$rawText = '';
|
||||
}
|
||||
|
||||
switch ($encoding) {
|
||||
case 0x00: // ISO-8859-1
|
||||
return mb_convert_encoding($rawText, 'utf-8', 'iso-8859-1');
|
||||
|
||||
case 0x01: // UTF-16 with BOM
|
||||
return mb_convert_encoding($rawText . "\00", 'utf-8', 'utf-16');
|
||||
|
||||
// Following is for id3v2.4.x only
|
||||
case 0x02: // UTF-16 without BOM
|
||||
return mb_convert_encoding($rawText . "\00", 'utf-8', 'utf-16');
|
||||
case 0x03: // UTF-8
|
||||
return $rawText;
|
||||
|
||||
default:
|
||||
throw new RuntimeException('Unknown text encoding type: ' . $encoding);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $frameSize
|
||||
* @param $raw
|
||||
@ -945,22 +995,7 @@ class Mp3Info {
|
||||
private function handleTextFrame($frameSize, $raw)
|
||||
{
|
||||
$data = unpack('C1encoding/A' . ($frameSize - 1) . 'information', $raw);
|
||||
|
||||
switch($data['encoding']) {
|
||||
case 0x00: # ISO-8859-1
|
||||
return mb_convert_encoding($data['information'], 'utf-8', 'iso-8859-1');
|
||||
case 0x01: # utf-16 with BOM
|
||||
return mb_convert_encoding($data['information'] . "\00", 'utf-8', 'utf-16');
|
||||
|
||||
# Following is for id3v2.4.x only
|
||||
case 0x02: # utf-16 without BOM
|
||||
return mb_convert_encoding($data['information'] . "\00", 'utf-8', 'utf-16');
|
||||
case 0x03: # utf-8
|
||||
return $data['information'];
|
||||
|
||||
default:
|
||||
throw new RuntimeException('Unknown text encoding type: '.$data['encoding']);
|
||||
}
|
||||
return $this->_getUtf8Text($data['encoding'], $data['information']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user