17db96d56Sopenharmony_ci# Copyright (C) 2001-2007 Python Software Foundation 27db96d56Sopenharmony_ci# Author: Anthony Baxter 37db96d56Sopenharmony_ci# Contact: email-sig@python.org 47db96d56Sopenharmony_ci 57db96d56Sopenharmony_ci"""Class representing audio/* type MIME documents.""" 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ci__all__ = ['MIMEAudio'] 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_cifrom io import BytesIO 107db96d56Sopenharmony_cifrom email import encoders 117db96d56Sopenharmony_cifrom email.mime.nonmultipart import MIMENonMultipart 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_ci 147db96d56Sopenharmony_ciclass MIMEAudio(MIMENonMultipart): 157db96d56Sopenharmony_ci """Class for generating audio/* MIME documents.""" 167db96d56Sopenharmony_ci 177db96d56Sopenharmony_ci def __init__(self, _audiodata, _subtype=None, 187db96d56Sopenharmony_ci _encoder=encoders.encode_base64, *, policy=None, **_params): 197db96d56Sopenharmony_ci """Create an audio/* type MIME document. 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ci _audiodata contains the bytes for the raw audio data. If this data 227db96d56Sopenharmony_ci can be decoded as au, wav, aiff, or aifc, then the 237db96d56Sopenharmony_ci subtype will be automatically included in the Content-Type header. 247db96d56Sopenharmony_ci Otherwise, you can specify the specific audio subtype via the 257db96d56Sopenharmony_ci _subtype parameter. If _subtype is not given, and no subtype can be 267db96d56Sopenharmony_ci guessed, a TypeError is raised. 277db96d56Sopenharmony_ci 287db96d56Sopenharmony_ci _encoder is a function which will perform the actual encoding for 297db96d56Sopenharmony_ci transport of the image data. It takes one argument, which is this 307db96d56Sopenharmony_ci Image instance. It should use get_payload() and set_payload() to 317db96d56Sopenharmony_ci change the payload to the encoded form. It should also add any 327db96d56Sopenharmony_ci Content-Transfer-Encoding or other headers to the message as 337db96d56Sopenharmony_ci necessary. The default encoding is Base64. 347db96d56Sopenharmony_ci 357db96d56Sopenharmony_ci Any additional keyword arguments are passed to the base class 367db96d56Sopenharmony_ci constructor, which turns them into parameters on the Content-Type 377db96d56Sopenharmony_ci header. 387db96d56Sopenharmony_ci """ 397db96d56Sopenharmony_ci if _subtype is None: 407db96d56Sopenharmony_ci _subtype = _what(_audiodata) 417db96d56Sopenharmony_ci if _subtype is None: 427db96d56Sopenharmony_ci raise TypeError('Could not find audio MIME subtype') 437db96d56Sopenharmony_ci MIMENonMultipart.__init__(self, 'audio', _subtype, policy=policy, 447db96d56Sopenharmony_ci **_params) 457db96d56Sopenharmony_ci self.set_payload(_audiodata) 467db96d56Sopenharmony_ci _encoder(self) 477db96d56Sopenharmony_ci 487db96d56Sopenharmony_ci 497db96d56Sopenharmony_ci_rules = [] 507db96d56Sopenharmony_ci 517db96d56Sopenharmony_ci 527db96d56Sopenharmony_ci# Originally from the sndhdr module. 537db96d56Sopenharmony_ci# 547db96d56Sopenharmony_ci# There are others in sndhdr that don't have MIME types. :( 557db96d56Sopenharmony_ci# Additional ones to be added to sndhdr? midi, mp3, realaudio, wma?? 567db96d56Sopenharmony_cidef _what(data): 577db96d56Sopenharmony_ci # Try to identify a sound file type. 587db96d56Sopenharmony_ci # 597db96d56Sopenharmony_ci # sndhdr.what() had a pretty cruddy interface, unfortunately. This is why 607db96d56Sopenharmony_ci # we re-do it here. It would be easier to reverse engineer the Unix 'file' 617db96d56Sopenharmony_ci # command and use the standard 'magic' file, as shipped with a modern Unix. 627db96d56Sopenharmony_ci hdr = data[:512] 637db96d56Sopenharmony_ci fakefile = BytesIO(hdr) 647db96d56Sopenharmony_ci for testfn in _rules: 657db96d56Sopenharmony_ci if res := testfn(hdr, fakefile): 667db96d56Sopenharmony_ci return res 677db96d56Sopenharmony_ci else: 687db96d56Sopenharmony_ci return None 697db96d56Sopenharmony_ci 707db96d56Sopenharmony_ci 717db96d56Sopenharmony_cidef rule(rulefunc): 727db96d56Sopenharmony_ci _rules.append(rulefunc) 737db96d56Sopenharmony_ci return rulefunc 747db96d56Sopenharmony_ci 757db96d56Sopenharmony_ci 767db96d56Sopenharmony_ci@rule 777db96d56Sopenharmony_cidef _aiff(h, f): 787db96d56Sopenharmony_ci if not h.startswith(b'FORM'): 797db96d56Sopenharmony_ci return None 807db96d56Sopenharmony_ci if h[8:12] in {b'AIFC', b'AIFF'}: 817db96d56Sopenharmony_ci return 'x-aiff' 827db96d56Sopenharmony_ci else: 837db96d56Sopenharmony_ci return None 847db96d56Sopenharmony_ci 857db96d56Sopenharmony_ci 867db96d56Sopenharmony_ci@rule 877db96d56Sopenharmony_cidef _au(h, f): 887db96d56Sopenharmony_ci if h.startswith(b'.snd'): 897db96d56Sopenharmony_ci return 'basic' 907db96d56Sopenharmony_ci else: 917db96d56Sopenharmony_ci return None 927db96d56Sopenharmony_ci 937db96d56Sopenharmony_ci 947db96d56Sopenharmony_ci@rule 957db96d56Sopenharmony_cidef _wav(h, f): 967db96d56Sopenharmony_ci # 'RIFF' <len> 'WAVE' 'fmt ' <len> 977db96d56Sopenharmony_ci if not h.startswith(b'RIFF') or h[8:12] != b'WAVE' or h[12:16] != b'fmt ': 987db96d56Sopenharmony_ci return None 997db96d56Sopenharmony_ci else: 1007db96d56Sopenharmony_ci return "x-wav" 101