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