mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 09:30:24 +00:00
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) });
|
|
}
|
|
|
|
}
|