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

1#!/usr/bin/env python3 

2 

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 

11 

12 # Import standard modules ... 

13 import os 

14 

15 # Import sub-functions ... 

16 from ..convert_bytes_to_pretty_bytes import convert_bytes_to_pretty_bytes 

17 

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 } 

29 

30 # Open FLAC read-only ... 

31 with open(fname, "rb") as fObj: 

32 # Create short-hand ... 

33 fsize = os.path.getsize(fname) # [B] 

34 

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 

38 

39 # Initialize flag ... 

40 last = False 

41 

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) 

46 

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 

52 

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] 

55 

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') 

59 

60 # Check if this is the last block before the frames ... 

61 if last: 

62 # Stop looping ... 

63 break 

64 

65 # Skip to the end of the block ... 

66 fObj.seek(val, os.SEEK_CUR)