Coverage for pyguymer3/media/print_FLAC_blocks.py: 5%
20 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-08 18:47 +0000
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-08 18:47 +0000
1#!/usr/bin/env python3
3# Define function ...
4def print_FLAC_blocks(
5 fname,
6 /,
7):
8 # NOTE: The following website has some very useful information on how to
9 # parse FLAC files.
10 # * https://xiph.org/flac/format.html
12 # Import standard modules ...
13 import os
15 # Import sub-functions ...
16 from ..convert_bytes_to_pretty_bytes import convert_bytes_to_pretty_bytes
18 # List block types ...
19 blocks = {
20 0 : "STREAMINFO",
21 1 : "PADDING",
22 2 : "APPLICATION",
23 3 : "SEEKTABLE",
24 4 : "VORBIS_COMMENT",
25 5 : "CUESHEET",
26 6 : "PICTURE",
27 127 : "INVALID",
28 }
30 # Open FLAC read-only ...
31 with open(fname, "rb") as fObj:
32 # Create short-hand ...
33 fsize = os.path.getsize(fname) # [B]
35 # Read magic marker and raise exception if it is not expected ...
36 if fObj.read(4).decode("utf-8") != "fLaC":
37 raise Exception(f"\"{fname}\" is not a FLAC") from None
39 # Initialize flag ...
40 last = False
42 # Loop over entire contents of FLAC ...
43 while fObj.tell() < fsize:
44 # Attempt to read 1 byte as a big-endian un-signed integer ...
45 name = int.from_bytes(fObj.read(1), byteorder = "big", signed = False)
47 # Check if this integer has the "last block" flag set and take it
48 # off ...
49 if name > 127:
50 last = True
51 name -= 128
53 # Attempt to read 3 bytes as a big-endian un-signed integer ...
54 val = int.from_bytes(fObj.read(3), byteorder = "big", signed = False) # [B]
56 # Print summary ...
57 size, units = convert_bytes_to_pretty_bytes(val + 4)
58 print(f'{blocks.get(name, "RESERVED")} is {size:6.1f} {units:3s} long')
60 # Check if this is the last block before the frames ...
61 if last:
62 # Stop looping ...
63 break
65 # Skip to the end of the block ...
66 fObj.seek(val, os.SEEK_CUR)