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