"""DDEX ERN mappings.""" import re from delivery_metadata.constants import ( CommercialModelType, InstrumentRole, LyricsExplicitness, ParticipantRole, ProductType, UseType, ) class DdexErnMapping: @property def lyrics_explicitness_to_parental_warning_type( self, ) -> dict[LyricsExplicitness, str]: return { LyricsExplicitness.EXPLICIT: "Explicit", LyricsExplicitness.CLEAN: "ExplicitContentEdited", # "": "NoAdviceAvailable", LyricsExplicitness.NOT_EXPLICIT: "NotExplicit", LyricsExplicitness.UNKNOWN: "Unknown", } @property def release_type_mapping(self) -> dict[ProductType, str]: return { ProductType.MUSIC_ALBUM: "Album", # "": "AlertToneRelease", # "": "AsPerContract", # "": "AudioBookRelease", # "": "AudioDramaRelease", # "": "BackCoverImageRelease", # "": "BookletBackImageRelease", # "": "BookletFrontImageRelease", # "": "BookletRelease", ProductType.MUSIC_BUNDLE: "Bundle", ProductType.CLASSICAL_ALBUM: "ClassicalAlbum", # "": "ClassicalDigitalBoxedSet", # "": "ClassicalMultimediaAlbum", # "film_concert": "ConcertVideo", # "": "DigitalBoxSetRelease", # "": "DjMix", # "": "Documentary", # "": "Drama", # "": "DramaticoMusicalVideoRelease", # "": "EBookRelease", ProductType.EP: "EP", # "tv_episode": "Episode", # "film_feature": "FeatureFilm", # "": "KaraokeRelease", # "": "LiveEventVideo", # "": "LogoRelease", # "": "LongFormMusicalWorkVideoRelease", # "": "LongFormNonMusicalWorkVideoRelease", # "": "LyricSheetRelease", # "": "MultimediaAlbum", # "": "MultimediaDigitalBoxedSet", # "": "MultimediaSingle", # "": "MusicalWorkBasedGameRelease", # "": "NonMusicalWorkBasedGameRelease", # "": "PlayList", # "music_ringback": "RingbackToneRelease", ProductType.RINGTONE: "RingtoneRelease", # "": "Season", # "": "Series", # "": "SheetMusicRelease", # "": "ShortFilm", ProductType.MUSIC_SINGLE: "Single", # "": "SingleResourceRelease", # "": "StemBundle", ProductType.VIDEO_ALBUM: "VideoAlbum", # "": "VideoMastertoneRelease", ProductType.VIDEO_SINGLE: "VideoSingle", # "": "WallpaperRelease", } @property def artist_role_mapping(self) -> dict[ParticipantRole, str]: return { # "": "Artist", # "": "Brand", ParticipantRole.COMPOSER: "Composer", ParticipantRole.TRACK_WRITER: "Composer", ParticipantRole.FEATURING: "FeaturedArtist", ParticipantRole.PERFORMER: "MainArtist", # "": "Unknown", } @property def audio_codec_type_mapping(self) -> dict[str, str]: return { "aac": "AAC", "pmd": "ADPCM", "mp2": "MP2", "mp3": "MP3", "pcm": "PCM", "qcp": "QCELP", "ra": "RealAudio", "amr": "AMR-NB", "awb": "AMR-WB", "flac": "FLAC", "flac16": "FLAC", "flac24": "FLAC", "wav": "PCM", "wav16": "PCM", "wav24": "PCM", "wav40": "PCM", "wma": "WMA", "atmos": "DolbyAtmosMasterADM", } @property def commercial_model_type_mapping(self) -> dict[CommercialModelType, str]: return { CommercialModelType.AD_SUPPORTED: "AdvertisementSupportedModel", CommercialModelType.CONTRACT: "AsPerContract", CommercialModelType.PAY: "PayAsYouGoModel", CommercialModelType.SUBSCRIPTION: "SubscriptionModel", } @property def image_codec_type_mapping(self) -> dict[str, str]: return { "gif": "GIF", "jpg": "JPEG", # "": "JPEG2000", "png": "PNG", "tif": "TIFF", } @property def contributor_role_mapping(self) -> dict[ParticipantRole, str]: # Roles that need to be explicitly mapped; cannot be programmatically derived maps = { ParticipantRole.CLUB_DJ: "ClubDJ", ParticipantRole.DJ: "DJ", ParticipantRole.PRODUCER: "StudioProducer", ParticipantRole.PUBLISHER: "MusicPublisher", ParticipantRole.SECOND_RECORDING_ENGINEER: "RecordingSecondEngineer", ParticipantRole.SECOND_REMIXING_ENGINEER: "RemixingSecondEngineer", ParticipantRole.STORY: "StoryTeller", ParticipantRole.TRACK_WRITER: "Composer", ParticipantRole.WHOLE_ORCHESTRA: "Orchestra", } # Roles that do not map to a DDEX value, will be UserDefined excluded_roles = { ParticipantRole.CAST, ParticipantRole.DIRECTOR, ParticipantRole.EDITOR, ParticipantRole.FEATURING, ParticipantRole.OTHER_COMPOSITIONAL_CONTRIBUTOR, ParticipantRole.OTHER_LABEL_PERSONNEL, ParticipantRole.OTHER_STUDIO_PERSONNEL, ParticipantRole.VIDEOGRAPHER, ParticipantRole.VOCALS_BEATBOXING, ParticipantRole.VOCALS_CHANTING, ParticipantRole.VOCALS_RAPPER, ParticipantRole.VOCALS_SHOUTING, ParticipantRole.VOCALS_SPOKEN_WORD, ParticipantRole.VOCALS_VOCAL_EFFECTS, ParticipantRole.VOCALS_WHISTLING, ParticipantRole.VOCALS_YODELING, } for role in ParticipantRole: if role not in maps and role not in excluded_roles: role_name = role.value.replace(" & ", " And ").title() maps[role] = re.sub(r"[^a-zA-Z0-9]", "", role_name) return maps @property def instrument_role_mapping(self) -> dict[InstrumentRole, str]: # Roles that need to be explicitly mapped; cannot be programmatically derived maps: dict[InstrumentRole, str] = { InstrumentRole.BRASS_ALPHORN: "Alpenhorn", InstrumentRole.BRASS_FLUEGELHORN: "Flugelhorn", InstrumentRole.BRASS_OTHER: "BrassInstrument", InstrumentRole.ELECTRONICS_SCRATCHING: "Turntable", InstrumentRole.GUITAR_DOBRO: "DobroGuitar", InstrumentRole.GUITAR_OTHER: "Guitar", InstrumentRole.KEYBOARDS_CELESTE: "Celesta", InstrumentRole.KEYBOARDS_ELECTRIC_KEYBOARD: "ElectricPiano", InstrumentRole.KEYBOARDS_OTHER: "Keyboard", InstrumentRole.OTHER_UNLISTED_PERFORMER_ROLE: "OtherInstrument", InstrumentRole.PERCUSSION_BASS_DRUM: "BassDrum(Concert)", InstrumentRole.PERCUSSION_HI_HAT: "HiHatCymbal", InstrumentRole.PERCUSSION_OTHER: "PercussionInstrument", InstrumentRole.PERCUSSION_STEEL_DRUM: "SteelDrums", InstrumentRole.PERCUSSION_TEMPLE_BLOCK: "TempleBlocks", InstrumentRole.PERCUSSION_TOM_TOM: "Toms", InstrumentRole.PERCUSSION_VIBRA_SLAP: "Vibraslap", InstrumentRole.PERCUSSION_WOODBLOCK: "WoodBlock", InstrumentRole.STRING_DULCIMER: "HammeredDulcimer", InstrumentRole.STRING_OTHER: "StringInstrument", InstrumentRole.WIND_INSTRUMENTS_OTHER: "WindInstrument", InstrumentRole.WIND_INSTRUMENTS_PICCOLO: "PiccoloFlute", } # Roles that do not map to a DDEX value, will be UserDefined excluded_roles = { InstrumentRole.BRASS_HORN, InstrumentRole.ELECTRONICS_LOOPS, InstrumentRole.ELECTRONICS_PROGRAMMER, InstrumentRole.ELECTRONICS_SAMPLER, InstrumentRole.ELECTRONICS_THEREMIN, InstrumentRole.ELECTRONICS_VOCODER, InstrumentRole.GUITAR_BASS_GUITAR, InstrumentRole.GUITAR_GUITAR_SYNTHESIZER, InstrumentRole.GUITAR_SLIDE_GUITAR, InstrumentRole.KEYBOARDS_HARMONIUM, InstrumentRole.PERCUSSION_BELLS, InstrumentRole.PERCUSSION_CLAPPING, InstrumentRole.PERCUSSION_DRUMS, InstrumentRole.PERCUSSION_ELECTRONIC_DRUMS, InstrumentRole.PERCUSSION_ELECTRONIC_PERCUSSION, InstrumentRole.WIND_INSTRUMENTS_ELECTRONIC, InstrumentRole.WIND_INSTRUMENTS_WHISTLE, } for role in InstrumentRole: if role not in maps and role not in excluded_roles: role_name = role.value.title() # Category prefixes need to be stripped for track performer instrument roles role_name = re.sub( r"^(Brass|Electronics|Guitar|Keyboards|Other|Percussion|String|Wind Instruments|Vocals) - ", "", role_name, ) maps[role] = re.sub(r"[^a-zA-Z0-9]", "", role_name) return maps @property def use_type_mapping(self) -> dict[UseType, str]: return { UseType.CONTRACT: "AsPerContract", UseType.CONDITIONAL_DOWNLOAD: "ConditionalDownload", UseType.NON_INTERACTIVE: "NonInteractiveStream", UseType.ON_DEMAND: "OnDemandStream", UseType.PERMANENT_DOWNLOAD: "PermanentDownload", UseType.RINGBACK: "UseAsRingbackTone", UseType.RINGTONE: "UseAsRingtone", UseType.LABEL: "UserMakeAvailableLabelProvided", UseType.STREAM: "Stream", }