mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-26 03:42:38 +00:00 
			
		
		
		
	 d8e8ddedf3
			
		
	
	
		d8e8ddedf3
		
	
	
	
	
		
			
			This container has several design goals: - Represent all common and relevant metadata fields of audio files in a unified way. - Allow perfect recreation of any metadata format from the in-memory structure. This requires that we allow non-detected fields to reside in an "untyped" miscellaneous collection. Like with pictures, plugins are free to store their metadata into the m_metadata field whenever they read it. It is recommended that this happens on loader creation; however failing to read metadata should not cause an error in the plugin.
		
			
				
	
	
		
			94 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			94 lines
		
	
	
	
		
			3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2023, kleines Filmröllchen <filmroellchen@serenityos.org>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #include "Metadata.h"
 | |
| #include <AK/Assertions.h>
 | |
| #include <LibCore/Version.h>
 | |
| 
 | |
| namespace Audio {
 | |
| 
 | |
| bool Person::is_artist() const
 | |
| {
 | |
|     return role == Person::Role::Artist
 | |
|         || role == Person::Role::Composer
 | |
|         || role == Person::Role::Conductor
 | |
|         || role == Person::Role::Lyricist
 | |
|         || role == Person::Role::Performer;
 | |
| }
 | |
| 
 | |
| Optional<StringView> Person::name_for_role() const
 | |
| {
 | |
|     switch (role) {
 | |
|     case Role::Artist:
 | |
|     case Role::Performer:
 | |
|         return {};
 | |
|     case Role::Lyricist:
 | |
|         return "Lyricist"sv;
 | |
|     case Role::Conductor:
 | |
|         return "Conductor"sv;
 | |
|     case Role::Publisher:
 | |
|         return "Publisher"sv;
 | |
|     case Role::Engineer:
 | |
|         return "Engineer"sv;
 | |
|     case Role::Composer:
 | |
|         return "Composer"sv;
 | |
|     }
 | |
|     VERIFY_NOT_REACHED();
 | |
| }
 | |
| 
 | |
| void Metadata::replace_encoder_with_serenity()
 | |
| {
 | |
|     auto version_or_error = Core::Version::read_long_version_string();
 | |
|     // Unset the encoder field in this case; we definitely want to replace the existing encoder field.
 | |
|     if (version_or_error.is_error())
 | |
|         encoder = {};
 | |
|     auto encoder_string = String::formatted("SerenityOS LibAudio {}", version_or_error.release_value());
 | |
|     if (encoder_string.is_error())
 | |
|         encoder = {};
 | |
|     encoder = encoder_string.release_value();
 | |
| }
 | |
| 
 | |
| Optional<String> Metadata::first_artist() const
 | |
| {
 | |
|     auto artist = people.find_if([](auto const& person) { return person.is_artist(); });
 | |
|     if (artist.is_end())
 | |
|         return {};
 | |
|     return artist->name;
 | |
| }
 | |
| 
 | |
| ErrorOr<Optional<String>> Metadata::all_artists(StringView concatenate_with) const
 | |
| {
 | |
|     // FIXME: This entire function could be similar to TRY(TRY(people.filter(...).try_map(...)).join(concatenate_with)) if these functional iterator transformers existed :^)
 | |
|     Vector<String> artist_texts;
 | |
|     TRY(artist_texts.try_ensure_capacity(people.size()));
 | |
|     for (auto const& person : people) {
 | |
|         if (!person.is_artist())
 | |
|             continue;
 | |
|         if (auto role_name = person.name_for_role(); role_name.has_value())
 | |
|             artist_texts.unchecked_append(TRY(String::formatted("{} ({})", person.name, role_name.release_value())));
 | |
|         else
 | |
|             artist_texts.unchecked_append(person.name);
 | |
|     }
 | |
|     if (artist_texts.is_empty())
 | |
|         return Optional<String> {};
 | |
|     return String::join(concatenate_with, artist_texts);
 | |
| }
 | |
| 
 | |
| ErrorOr<void> Metadata::add_miscellaneous(String const& field, String value)
 | |
| {
 | |
|     // FIXME: Since try_ensure does not return a reference to the contained value, we have to retrieve it separately.
 | |
|     //        This is a try_ensure bug that should be fixed.
 | |
|     (void)TRY(miscellaneous.try_ensure(field, []() { return Vector<String> {}; }));
 | |
|     auto& values_for_field = miscellaneous.get(field).release_value();
 | |
|     return values_for_field.try_append(move(value));
 | |
| }
 | |
| 
 | |
| ErrorOr<void> Metadata::add_person(Person::Role role, String name)
 | |
| {
 | |
|     return people.try_append(Person { role, move(name) });
 | |
| }
 | |
| 
 | |
| }
 |