mirror of
https://github.com/iluvcapra/wavinfo.git
synced 2025-12-31 08:50:41 +00:00
All existing tests pass
This commit is contained in:
@@ -11,8 +11,8 @@ from dataclasses import dataclass
|
||||
import encodings
|
||||
from .riff_parser import ChunkDescriptor
|
||||
|
||||
from struct import unpack, unpack_from, calcsize
|
||||
from typing import Optional, NamedTuple, List
|
||||
from struct import unpack, calcsize
|
||||
from typing import Optional, NamedTuple, List, Dict, Any
|
||||
|
||||
#: Country Codes used in the RIFF standard to resolve locale. These codes
|
||||
#: appear in CSET and LTXT metadata.
|
||||
@@ -113,8 +113,8 @@ class CueEntry(NamedTuple):
|
||||
|
||||
@classmethod
|
||||
def read(cls, data: bytes) -> 'CueEntry':
|
||||
assert len(data) == calcsize(cls.Format), \
|
||||
"cue data size incorrect, expected {calcsize(cls.Format)} found {len(cues_data)}"
|
||||
assert len(data) == cls.format_size(), \
|
||||
f"cue data size incorrect, expected {calcsize(cls.Format)} found {len(data)}"
|
||||
|
||||
parsed = unpack(cls.Format, data)
|
||||
|
||||
@@ -178,12 +178,13 @@ class WavCuesReader:
|
||||
if cues is not None:
|
||||
cues_data = cues.read_data(f)
|
||||
assert len(cues_data) >= 4, "cue metadata too short"
|
||||
cues_count = unpack("<I", cues_data)
|
||||
|
||||
offset = calcsize("<I")
|
||||
for _ in cues_count:
|
||||
cue_bytes = cues_data[offset: CueEntry.format_size() ]
|
||||
cues_count = unpack("<I", cues_data[0:offset])
|
||||
|
||||
for _ in range(cues_count[0]):
|
||||
cue_bytes = cues_data[offset: offset + CueEntry.format_size()]
|
||||
cue_list.append(CueEntry.read(cue_bytes))
|
||||
offset += CueEntry.format_size()
|
||||
|
||||
label_list = []
|
||||
for labl in labls:
|
||||
@@ -202,6 +203,12 @@ class WavCuesReader:
|
||||
return WavCuesReader(cues=cue_list, labels=label_list,
|
||||
ranges=range_list)
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
return dict(cues=[c.__dict__ for c in self.cues],
|
||||
labels=[l.__dict__ for l in self.labels],
|
||||
ranges=[r.__dict__ for r in self.ranges])
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -73,6 +73,9 @@ class WavInfoReader:
|
||||
#: RIFF INFO metadata.
|
||||
self.info :Optional[WavInfoChunkReader]= None
|
||||
|
||||
#: RIFF CUE, LABL and LTXT metadata.
|
||||
self.cues :Optional[WavCuesReader] = None
|
||||
|
||||
if hasattr(path, 'read'):
|
||||
self.get_wav_info(path)
|
||||
self.url = 'about:blank'
|
||||
@@ -102,7 +105,7 @@ class WavInfoReader:
|
||||
self.adm = self._get_adm(wavfile)
|
||||
self.info = self._get_info(wavfile, encoding=self.info_encoding)
|
||||
self.dolby = self._get_dbmd(wavfile)
|
||||
# self.cue = self._get_cue(wavfile)
|
||||
self.cues = self._get_cue(wavfile)
|
||||
self.data = self._describe_data()
|
||||
|
||||
def _find_chunk_data(self, ident, from_stream, default_none=False) -> Optional[bytes]:
|
||||
@@ -188,15 +191,19 @@ class WavInfoReader:
|
||||
return WavIXMLFormat(ixml_data.rstrip(b'\0')) if ixml_data else None
|
||||
|
||||
def _get_cue(self, f):
|
||||
cue = next((cue_chunk for cue_chunk in self.main_list if cue_chunk.ident == b'cue '), None)
|
||||
cue = next((cue_chunk for cue_chunk in self.main_list if \
|
||||
type(cue_chunk) is ChunkDescriptor and \
|
||||
cue_chunk.ident == b'cue '), None)
|
||||
|
||||
adtl = self._find_list_chunk(b'adtl')
|
||||
labls = []
|
||||
ltxts = []
|
||||
if adtl is not None:
|
||||
labls = [child.read_data(f) for child in adtl.children if child.ident == b'labl']
|
||||
ltxts = [child.read_data(f) for child in adtl.children if child.ident == b'ltxt']
|
||||
labls = [child for child in adtl.children if child.ident == b'labl']
|
||||
ltxts = [child for child in adtl.children if child.ident == b'ltxt']
|
||||
|
||||
return WavCuesReader.merge(f, cue, labls, ltxts)
|
||||
return WavCuesReader.merge(f, cue, labls, ltxts,
|
||||
fallback_encoding=self.info_encoding)
|
||||
|
||||
def walk(self) -> Generator[str,str,Any]: #FIXME: this should probably be named "iter()"
|
||||
"""
|
||||
@@ -204,10 +211,10 @@ class WavInfoReader:
|
||||
|
||||
:yields: tuples of the *scope*, *key*, and *value* of
|
||||
each metadatum. The *scope* value will be one of
|
||||
"fmt", "data", "ixml", "bext", "info", "dolby", "cue" or "adm".
|
||||
"fmt", "data", "ixml", "bext", "info", "dolby", "cues" or "adm".
|
||||
"""
|
||||
|
||||
scopes = ('fmt', 'data', 'ixml', 'bext', 'info', 'adm', 'dolby')
|
||||
scopes = ('fmt', 'data', 'ixml', 'bext', 'info', 'adm', 'cues', 'dolby')
|
||||
|
||||
for scope in scopes:
|
||||
if scope in ['fmt', 'data']:
|
||||
|
||||
Reference in New Issue
Block a user