Ejemplo n.º 1
0
def _GenVersion(output):
    """Writes the version.h file to the given file object."""
    version = GetVersionStr()
    major, minor, revision, tag = ParseVersion(version)

    assert major >= 0 and major <= _MAX_VERSION
    assert minor >= 0 and minor <= _MAX_VERSION
    assert revision >= 0 and revision <= _MAX_VERSION
    assert tag >= 0 and tag <= _MAX_VERSION
    writer = embed_utils.CodeWriter(output)
    writer.Write('#define SHAKA_VERSION_MAJOR %dULL' % major)
    writer.Write('#define SHAKA_VERSION_MINOR %dULL' % minor)
    writer.Write('#define SHAKA_VERSION_REVISION %dULL' % revision)
    writer.Write('#define SHAKA_VERSION_TAG %dULL' % tag)
    writer.Write('#define SHAKA_VERSION_INT ('
                 '(SHAKA_VERSION_MAJOR << 48ULL) | '
                 '(SHAKA_VERSION_MINOR << 32ULL) | '
                 '(SHAKA_VERSION_REVISION << 16ULL) | (SHAKA_VERSION_TAG))')
    writer.Write('#define SHAKA_VERSION_STR "%s"' % version)
    writer.Write()

    writer.Write('#ifdef __cplusplus')
    writer.Write('extern "C" {')
    writer.Write('#endif  // __cplusplus')

    writer.Write('/** @return The runtime version of the library. */')
    writer.Write('const char* GetShakaEmbeddedVersion(void);')

    writer.Write('#ifdef __cplusplus')
    writer.Write('}')
    writer.Write('#endif  // __cplusplus')
def GenerateFile(plugins, output):
    """Generates a C++ file which registers the given implementations."""
    writer = embed_utils.CodeWriter(output)
    writer.Write('#include <atomic>')
    writer.Write()
    writer.Write('#include "shaka/eme/implementation_registry.h"')
    writer.Write()

    for header in sorted(_GetHeaders(plugins)):
        writer.Write('#include "%s"', header)
    writer.Write()

    with writer.Namespace('shaka'):
        writer.Write('void RegisterDefaultKeySystems();')
        writer.Write()
        with writer.Block('void RegisterDefaultKeySystems()'):
            # This ensures the key systems are registered exactly once, even if this
            # is called from multiple threads.  The compare_exchange_strong will
            # atomically check if it is false and replace with true on only one
            # thread.
            writer.Write('static std::atomic<bool> called{false};')
            writer.Write('bool expected = false;')
            with writer.Block(
                    'if (called.compare_exchange_strong(expected, true))'):
                for plugin in plugins:
                    for impl in plugin['implementations']:
                        writer.Write(
                            'eme::ImplementationRegistry::AddImplementation(')
                        writer.Write('    "%s", new %s);', impl['key_system'],
                                     impl['factory_type'])
def _GenerateObjcInternalHeader(results, f, name, public_header, objc_header):
    """Generates the header for the internal Objective-C type."""
    writer = embed_utils.CodeWriter(f)
    writer.Write('#ifndef SHAKA_EMBEDDED_OBJC_%s_INTERNAL_H_', name.upper())
    writer.Write('#define SHAKA_EMBEDDED_OBJC_%s_INTERNAL_H_', name.upper())
    writer.Write()
    writer.Write('#import "%s"', objc_header)
    writer.Write('#include "%s"', public_header)
    writer.Write('#include "src/util/objc_utils.h"')
    writer.Write()
    for t in results.types:
        with writer.Block('@interface Shaka%s()' % t.name):
            writer.Write('shaka::%s value;', t.name)
        writer.Write()
        writer.Write('- (instancetype)initWithCpp:(const shaka::%s&)obj;',
                     t.name)
        writer.Write()
        writer.Write('- (const shaka::%s&)toCpp;', t.name)
        writer.Write()
        writer.Write('@end')
        writer.Write()
        writer.Write('template <>')
        with writer.Block('struct shaka::util::ObjcConverter<shaka::%s>' %
                          t.name,
                          semicolon=True):
            with writer.Block('static Shaka%s* ToObjc(const shaka::%s& val)' %
                              (t.name, t.name)):
                writer.Write('return [[Shaka%s alloc] initWithCpp:val];',
                             t.name)
            writer.Write()
        writer.Write()
        writer.Write()

    writer.Write('#endif  // SHAKA_EMBEDDED_OBJC_%s_INTERNAL_H_', name.upper())
def _GenerateObjcHeader(results, f, name):
    """Generates the header for the public Objective-C type."""
    other_types = [t.name for t in results.types]
    writer = embed_utils.CodeWriter(f)
    writer.Write('#ifndef SHAKA_EMBEDDED_OBJC_%s_H_', name.upper())
    writer.Write('#define SHAKA_EMBEDDED_OBJC_%s_H_', name.upper())
    writer.Write()
    writer.Write('#import <Foundation/Foundation.h>')
    writer.Write()
    writer.Write('#include "macros.h"')
    writer.Write()
    for t in results.types:
        if t.doc:
            writer.Write(_FormatDoc(t, indent=0))
        writer.Write('SHAKA_EXPORT')
        writer.Write('@interface Shaka%s : NSObject', t.name)
        writer.Write()

        for attr in t.attributes:
            if attr.doc:
                writer.Write(_FormatDoc(attr, indent=0))
            writer.Write('@property (atomic, readonly) %s %s;',
                         _MapObjcType(attr.type, other_types),
                         _GetObjcName(attr))
            writer.Write()

        writer.Write('@end')
        writer.Write()
        writer.Write()

    writer.Write('#endif  // SHAKA_EMBEDDED_OBJC_%s_H_', name.upper())
def _GeneratePublicHeader(results, f, name):
    """Generates the header for the public C++ type."""
    other_types = [t.name for t in results.types]
    writer = embed_utils.CodeWriter(f)
    writer.Write('#ifndef SHAKA_EMBEDDED_%s_H_', name.upper())
    writer.Write('#define SHAKA_EMBEDDED_%s_H_', name.upper())
    writer.Write()
    writer.Write('#include <memory>')
    writer.Write('#include <string>')
    writer.Write('#include <unordered_map>')
    writer.Write('#include <vector>')
    writer.Write()
    writer.Write('#include "macros.h"')
    writer.Write('#include "optional.h"')
    writer.Write()
    with writer.Namespace('shaka'):
        with writer.Namespace('js'):
            for t in results.types:
                writer.Write('struct %s;', t.name)
        writer.Write()

        for t in results.types:
            if t.doc:
                writer.Write(_FormatDoc(t, indent=0))
            with writer.Block('class SHAKA_EXPORT %s final' % t.name,
                              semicolon=True):
                writer.Write('public:', offset=-1)
                writer.Write('%s();', t.name)
                writer.Write('%s(js::%s&& internal);', t.name, t.name)
                writer.Write('%s(const %s&);', t.name, t.name)
                writer.Write('%s(%s&&);', t.name, t.name)
                writer.Write('~%s();', t.name)
                writer.Write()
                writer.Write('%s& operator=(const %s&);', t.name, t.name)
                writer.Write('%s& operator=(%s&&);', t.name, t.name)
                writer.Write()

                for attr in t.attributes:
                    if attr.doc:
                        writer.Write(_FormatDoc(attr, indent=2))
                    writer.Write(
                        '%s %s() const;',
                        _MapCppType(attr.type,
                                    other_types,
                                    is_public=True,
                                    is_ref=True), _GetPublicFieldName(attr))
                writer.Write()

                writer.Write(
                    '/** INTERNAL USE ONLY: Get the internal representation '
                    'of this object. */')
                writer.Write('js::%s GetInternal() const;', t.name)
                writer.Write()
                writer.Write('private:', offset=-1)
                writer.Write('class Impl;')
                writer.Write('std::shared_ptr<Impl> impl_;')
            writer.Write()

    writer.Write()
    writer.Write('#endif  // SHAKA_EMBEDDED_%s_H_', name.upper())
def _GenerateJsSource(results, f, header):
  """Generates the source file for the JavaScript mapping type."""
  writer = embed_utils.CodeWriter(f)
  writer.Write('#include "%s"', header)
  writer.Write()
  with writer.Namespace('shaka'):
    with writer.Namespace('js'):
      for t in results.types:
        writer.Write('DEFINE_STRUCT_SPECIAL_METHODS_MOVE_ONLY(%s);', t.name)
        writer.Write()
def _GenerateJsHeader(results, f, name, public_header):
    """Generates the header for the JavaScript mapping type."""
    other_types = [t.name for t in results.types]
    writer = embed_utils.CodeWriter(f)
    writer.Write('#ifndef SHAKA_EMBEDDED_INTERNAL_%s_H_', name.upper())
    writer.Write('#define SHAKA_EMBEDDED_INTERNAL_%s_H_', name.upper())
    writer.Write()
    writer.Write('#include <string>')
    writer.Write('#include <vector>')
    writer.Write()
    writer.Write('#include "shaka/optional.h"')
    writer.Write('#include "%s"', public_header)
    writer.Write('#include "src/mapping/convert_js.h"')
    writer.Write('#include "src/mapping/struct.h"')
    writer.Write()
    with writer.Namespace('shaka'):
        with writer.Namespace('js'):
            for t in results.types:
                with writer.Block('struct %s : Struct' % t.name,
                                  semicolon=True):
                    writer.Write(
                        'DECLARE_STRUCT_SPECIAL_METHODS_MOVE_ONLY(%s);',
                        t.name)
                    writer.Write()

                    for attr in t.attributes:
                        writer.Write(
                            'ADD_DICT_FIELD(%s, %s);', attr.name,
                            _MapCppType(attr.type,
                                        other_types,
                                        is_public=False))
                writer.Write()
        writer.Write()

        for t in results.types:
            writer.Write('template <>')
            with writer.Block('struct impl::ConvertHelper<shaka::%s, void>' %
                              t.name,
                              semicolon=True):
                with writer.Block(
                        'static bool FromJsValue(Handle<JsValue> source, '
                        'shaka::%s* dest)' % t.name):
                    writer.Write('shaka::js::%s temp;', t.name)
                    with writer.Block(
                            'if (!ConvertHelper<shaka::js::%s>::FromJsValue('
                            'source, &temp))' % t.name):
                        writer.Write('return false;')
                    writer.Write('*dest = shaka::%s(std::move(temp));', t.name)
                    writer.Write('return true;')
            writer.Write()

    writer.Write()
    writer.Write('#endif  // SHAKA_EMBEDDED_INTERNAL_%s_H_', name.upper())
def _GeneratePublicSource(results, f, public_header, internal_header):
    """Generates the source for the public C++ type."""
    other_types = [t.name for t in results.types]
    writer = embed_utils.CodeWriter(f)
    writer.Write('#include "%s"', public_header)
    writer.Write()
    writer.Write('#include "%s"', internal_header)
    writer.Write()
    with writer.Namespace('shaka'):
        for t in results.types:
            with writer.Block('class %s::Impl' % t.name, semicolon=True):
                writer.Write('public:', offset=-1)
                writer.Write('const js::%s value;', t.name)
            writer.Write()

            writer.Write('%s::%s() : impl_(new Impl) {}', t.name, t.name)
            writer.Write(
                '%s::%s(const js::%s& internal) : impl_(new Impl{internal}) {}',
                t.name, t.name, t.name)
            writer.Write('%s::%s(const %s&) = default;', t.name, t.name,
                         t.name)
            writer.Write('%s::%s(%s&&) = default;', t.name, t.name, t.name)
            writer.Write('%s::~%s() {}', t.name, t.name)
            writer.Write()
            writer.Write('%s& %s::operator=(const %s&) = default;', t.name,
                         t.name, t.name)
            writer.Write('%s& %s::operator=(%s&&) = default;', t.name, t.name,
                         t.name)
            writer.Write()

            for attr in t.attributes:
                with writer.Block(
                        '%s %s::%s() const' %
                    (_MapCppType(attr.type, other_types, is_public=True),
                     t.name, _GetPublicFieldName(attr))):
                    if attr.type.name == 'sequence':
                        writer.Write(
                            'return {impl_->value.%s.begin(), impl_->value.%s.end()};',
                            attr.name, attr.name)
                    else:
                        writer.Write('return impl_->value.%s;', attr.name)
                writer.Write()
            writer.Write()

            with writer.Block('const js::%s& %s::GetInternal() const' %
                              (t.name, t.name)):
                writer.Write('return impl_->value;')
            writer.Write()
            writer.Write()
def _GenerateJsSource(results, f, header):
    """Generates the source file for the JavaScript mapping type."""
    writer = embed_utils.CodeWriter(f)
    writer.Write('#include "%s"', header)
    writer.Write()
    with writer.Namespace('shaka'):
        with writer.Namespace('js'):
            for t in results.types:
                writer.Write('%s::%s() {}', t.name, t.name)
                writer.Write('%s::%s(const %s&) = default;', t.name, t.name,
                             t.name)
                writer.Write('%s::%s(%s&&) = default;', t.name, t.name, t.name)
                writer.Write('%s::~%s() {}', t.name, t.name)
                writer.Write()
                writer.Write('%s& %s::operator=(const %s&) = default;', t.name,
                             t.name, t.name)
                writer.Write('%s& %s::operator=(%s&&) = default;', t.name,
                             t.name, t.name)
                writer.Write()
                writer.Write()
def _GenerateObjcSource(results, f, header, objc_internal_header):
    """Generates the source for the public Objective-C type."""
    other_types = [t.name for t in results.types]
    writer = embed_utils.CodeWriter(f)
    writer.Write('#import "%s"', header)
    writer.Write('#import "%s"', objc_internal_header)
    writer.Write('#import "src/util/objc_utils.h"')
    writer.Write()
    for t in results.types:
        writer.Write('@implementation Shaka%s', t.name)
        writer.Write()

        with writer.Block('- (instancetype)initWithCpp:(const shaka::%s&)obj' %
                          t.name):
            with writer.Block('if ((self = [super init]))'):
                writer.Write('self->value = obj;')
            writer.Write('return self;')
        writer.Write()

        with writer.Block('- (const shaka::%s&)toCpp' % t.name):
            writer.Write('return self->value;')
        writer.Write()

        for attr in t.attributes:
            with writer.Block(
                    '- (%s)%s' %
                (_MapObjcType(attr.type, other_types), _GetObjcName(attr))):
                writer.Write(
                    'return shaka::util::ObjcConverter<%s>::ToObjc(self->value.%s());',
                    _MapCppType(attr.type, other_types, is_public=True),
                    _GetPublicFieldName(attr))
            writer.Write()

        writer.Write('@end')
        writer.Write()
        writer.Write()
def _GenerateObjcHeader(results, f, name):
    """Generates the header for the public Objective-C type."""
    other_types = [t.name for t in results.types]
    writer = embed_utils.CodeWriter(f)
    writer.Write('#ifndef SHAKA_EMBEDDED_OBJC_%s_H_', name.upper())
    writer.Write('#define SHAKA_EMBEDDED_OBJC_%s_H_', name.upper())
    writer.Write()
    writer.Write('#import <Foundation/Foundation.h>')
    writer.Write()
    writer.Write('#include "macros.h"')
    writer.Write()
    writer.Write('NS_ASSUME_NONNULL_BEGIN')
    writer.Write()
    for t in results.types:
        if t.doc:
            writer.Write(_FormatDoc(t, indent=0))
        writer.Write('SHAKA_EXPORT')
        writer.Write('@interface Shaka%s : NSObject', t.name)
        writer.Write()

        for attr in t.members:
            if attr.doc:
                writer.Write(_FormatDoc(attr, indent=0))
            objc_t = _MapObjcType(attr.type, other_types)
            writer.Write('@property (atomic, readonly%s) %s%s;',
                         ', nullable' if attr.type.nullable else '',
                         objc_t + ('' if objc_t.endswith('*') else ' '),
                         _GetObjcName(attr))
            writer.Write()

        writer.Write('@end')
        writer.Write()
        writer.Write()

    writer.Write('NS_ASSUME_NONNULL_END')
    writer.Write('#endif  // SHAKA_EMBEDDED_OBJC_%s_H_', name.upper())
def _GeneratePublicSource(results, f, public_header, internal_header):
    """Generates the source for the public C++ type."""
    other_types = [t.name for t in results.types]
    writer = embed_utils.CodeWriter(f)
    writer.Write('#include "%s"', public_header)
    writer.Write()
    writer.Write('#include "%s"', internal_header)
    writer.Write()
    with writer.Namespace('shaka'):
        for t in results.types:
            with writer.Block('class %s::Impl' % t.name, semicolon=True):
                writer.Write('public:', offset=-1)
                for attr in t.attributes:
                    writer.Write('const %s %s{};' % (_MapCppType(
                        attr.type, other_types, is_public=True), attr.name))
                writer.Write()

                writer.Write('Impl() {}')
                writer.Write('Impl(js::%s&& internal)', t.name)
                for i, attr in enumerate(t.attributes):
                    if attr.type.name in {'sequence', 'record'}:
                        inner = (
                            'std::make_move_iterator(internal.%s.begin()), ' +
                            'std::make_move_iterator(internal.%s.end())') % (
                                attr.name, attr.name)
                    else:
                        inner = 'std::move(internal.%s)' % attr.name
                    writer.Write('  %s %s(%s)%s', ':' if i == 0 else ' ',
                                 attr.name, inner,
                                 ' {}' if i == len(t.attributes) - 1 else ',')
            writer.Write()

            writer.Write('%s::%s() : impl_(new Impl) {}', t.name, t.name)
            writer.Write(
                '%s::%s(js::%s&& internal) : impl_(new Impl{std::move(internal)}) {}',
                t.name, t.name, t.name)
            writer.Write('%s::%s(const %s&) = default;', t.name, t.name,
                         t.name)
            writer.Write('%s::%s(%s&&) = default;', t.name, t.name, t.name)
            writer.Write('%s::~%s() {}', t.name, t.name)
            writer.Write()
            writer.Write('%s& %s::operator=(const %s&) = default;', t.name,
                         t.name, t.name)
            writer.Write('%s& %s::operator=(%s&&) = default;', t.name, t.name,
                         t.name)
            writer.Write()

            for attr in t.attributes:
                with writer.Block('%s %s::%s() const' % (_MapCppType(
                        attr.type, other_types, is_public=True,
                        is_ref=True), t.name, _GetPublicFieldName(attr))):
                    writer.Write('return impl_->%s;', attr.name)
                writer.Write()
            writer.Write()

            with writer.Block('js::%s %s::GetInternal() const' %
                              (t.name, t.name)):
                writer.Write('js::%s ret;', t.name)
                for i, attr in enumerate(t.attributes):
                    if (attr.type.name == 'sequence'
                            and attr.type.element_type.name in other_types):
                        with writer.Block(
                                'for (const auto& item : impl_->%s)' %
                                attr.name):
                            writer.Write(
                                'ret.%s.emplace_back(item.GetInternal());',
                                attr.name)
                    elif (attr.type.name == 'record'
                          and attr.type.element_type[1].name in other_types):
                        with writer.Block(
                                'for (const auto& item : impl_->%s)' %
                                attr.name):
                            writer.Write(
                                'ret.%s.emplace(item.first, item.second.GetInternal());',
                                attr.name)
                    elif attr.type.name in other_types:
                        writer.Write('ret.%s = impl_->%s.GetInternal();',
                                     attr.name, attr.name)
                    else:
                        writer.Write('ret.%s = impl_->%s;', attr.name,
                                     attr.name)
                writer.Write('return ret;')
            writer.Write()
            writer.Write()
Ejemplo n.º 13
0
def _GenConfig(parsed_args, out):
    writer = embed_utils.CodeWriter(out)
    if parsed_args.sdl_utils:
        writer.Write('#define SHAKA_SDL_UTILS 1')
    else:
        writer.Write('#undef SHAKA_SDL_UTILS')
def _GenConfig(parsed_args, out):
    writer = embed_utils.CodeWriter(out)
    _WriteFlag(writer, parsed_args.sdl_audio, 'SHAKA_SDL_AUDIO')
    _WriteFlag(writer, parsed_args.sdl_video, 'SHAKA_SDL_VIDEO')
    _WriteFlag(writer, parsed_args.media_player, 'SHAKA_DEFAULT_MEDIA_PLAYER')