mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-12 09:20:36 +00:00
SoundPlayer: Make M3UParser more idiomatic
Let's use the nice APIs we have, and make the M3U parser a bit more readable, shorter, and resilient.
This commit is contained in:
parent
3126b78903
commit
0812965f50
Notes:
sideshowbarker
2024-07-18 01:52:45 +09:00
Author: https://github.com/lpereira Commit: https://github.com/SerenityOS/serenity/commit/0812965f505 Pull-request: https://github.com/SerenityOS/serenity/pull/10278 Reviewed-by: https://github.com/kleinesfilmroellchen ✅
1 changed files with 57 additions and 71 deletions
|
@ -9,6 +9,7 @@
|
|||
#include <AK/RefPtr.h>
|
||||
#include <AK/ScopeGuard.h>
|
||||
#include <AK/Utf8View.h>
|
||||
#include <LibCore/File.h>
|
||||
|
||||
M3UParser::M3UParser()
|
||||
{
|
||||
|
@ -16,22 +17,11 @@ M3UParser::M3UParser()
|
|||
|
||||
NonnullOwnPtr<M3UParser> M3UParser::from_file(const String path)
|
||||
{
|
||||
auto parser = make<M3UParser>();
|
||||
VERIFY(!path.is_null() && !path.is_empty() && !path.is_whitespace());
|
||||
parser->m_use_utf8 = path.ends_with(".m3u8", AK::CaseSensitivity::CaseInsensitive);
|
||||
FILE* file = fopen(path.characters(), "r");
|
||||
ScopeGuard file_guard = [&] { fclose(file); };
|
||||
VERIFY(file != nullptr);
|
||||
fseek(file, 0, SEEK_END);
|
||||
size_t file_size = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
VERIFY(file_size > 0);
|
||||
Vector<u8> temp_buffer;
|
||||
temp_buffer.resize(file_size);
|
||||
auto bytes_read = fread(temp_buffer.data(), 1, file_size, file);
|
||||
VERIFY(bytes_read == file_size);
|
||||
parser->m_m3u_raw_data = *new String(temp_buffer.span(), NoChomp);
|
||||
return parser;
|
||||
auto file_result = Core::File::open(path, Core::OpenMode::ReadOnly);
|
||||
VERIFY(!file_result.is_error());
|
||||
auto contents = file_result.value()->read_all();
|
||||
auto use_utf8 = path.ends_with(".m3u8", CaseSensitivity::CaseInsensitive);
|
||||
return from_memory(String { contents, NoChomp }, use_utf8);
|
||||
}
|
||||
|
||||
NonnullOwnPtr<M3UParser> M3UParser::from_memory(const String& m3u_contents, bool utf8)
|
||||
|
@ -47,63 +37,59 @@ NonnullOwnPtr<Vector<M3UEntry>> M3UParser::parse(bool include_extended_info)
|
|||
{
|
||||
auto vec = make<Vector<M3UEntry>>();
|
||||
|
||||
bool has_extended_info_tag = false;
|
||||
if (!m_use_utf8) {
|
||||
auto lines = m_m3u_raw_data.split_view('\n');
|
||||
|
||||
if (include_extended_info) {
|
||||
if (lines[0] == "#EXTM3U")
|
||||
has_extended_info_tag = true;
|
||||
}
|
||||
|
||||
M3UExtendedInfo metadata_for_next_file {};
|
||||
for (auto& line : lines) {
|
||||
line = line.trim_whitespace();
|
||||
M3UEntry entry {};
|
||||
if (line.starts_with('#') && has_extended_info_tag) {
|
||||
if (line.starts_with("#EXTINF:")) {
|
||||
auto data = line.substring_view(8);
|
||||
auto separator = data.find(',');
|
||||
VERIFY(separator.has_value());
|
||||
auto seconds = data.substring_view(0, separator.value());
|
||||
VERIFY(!seconds.is_whitespace() && !seconds.is_null() && !seconds.is_empty());
|
||||
metadata_for_next_file.track_length_in_seconds = seconds.to_uint();
|
||||
auto display_name = data.substring_view(seconds.length() + 1);
|
||||
VERIFY(!display_name.is_empty() && !display_name.is_null() && !display_name.is_empty());
|
||||
metadata_for_next_file.track_display_title = display_name;
|
||||
//TODO: support the alternative, non-standard #EXTINF value of a key=value dictionary
|
||||
} else if (line.starts_with("#PLAYLIST:")) {
|
||||
auto name = line.substring_view(10);
|
||||
VERIFY(!name.is_empty());
|
||||
m_parsed_playlist_title = name;
|
||||
} else if (line.starts_with("#EXTGRP:")) {
|
||||
auto name = line.substring_view(8);
|
||||
VERIFY(!name.is_empty());
|
||||
metadata_for_next_file.group_name = name;
|
||||
} else if (line.starts_with("#EXTALB:")) {
|
||||
auto name = line.substring_view(8);
|
||||
VERIFY(!name.is_empty());
|
||||
metadata_for_next_file.album_title = name;
|
||||
} else if (line.starts_with("#EXTART:")) {
|
||||
auto name = line.substring_view(8);
|
||||
VERIFY(!name.is_empty());
|
||||
metadata_for_next_file.album_artist = name;
|
||||
} else if (line.starts_with("#EXTGENRE:")) {
|
||||
auto name = line.substring_view(10);
|
||||
VERIFY(!name.is_empty());
|
||||
metadata_for_next_file.album_genre = name;
|
||||
}
|
||||
//TODO: Support M3A files (M3U files with embedded mp3 files)
|
||||
} else {
|
||||
entry.path = line;
|
||||
entry.extended_info = metadata_for_next_file;
|
||||
vec->append(entry);
|
||||
metadata_for_next_file = {};
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (m_use_utf8) {
|
||||
//TODO: Implement M3U8 parsing
|
||||
TODO();
|
||||
return vec;
|
||||
}
|
||||
|
||||
auto lines = m_m3u_raw_data.split_view('\n');
|
||||
|
||||
bool has_extended_info_tag = include_extended_info && (lines[0] == "#EXTM3U");
|
||||
|
||||
M3UExtendedInfo metadata_for_next_file {};
|
||||
for (auto& line : lines) {
|
||||
line = line.trim_whitespace();
|
||||
|
||||
if (!has_extended_info_tag || !line.starts_with('#')) {
|
||||
vec->append({ line, metadata_for_next_file });
|
||||
metadata_for_next_file = {};
|
||||
continue;
|
||||
}
|
||||
|
||||
auto tag = [&line](StringView tag_name) -> Optional<StringView> {
|
||||
if (line.starts_with(tag_name)) {
|
||||
auto value = line.substring_view(tag_name.length());
|
||||
VERIFY(!value.is_empty());
|
||||
return value;
|
||||
}
|
||||
return {};
|
||||
};
|
||||
|
||||
if (auto ext_inf = tag("#EXTINF:"); ext_inf.has_value()) {
|
||||
auto separator = ext_inf.value().find(',');
|
||||
VERIFY(separator.has_value());
|
||||
auto seconds = ext_inf.value().substring_view(0, separator.value());
|
||||
VERIFY(!seconds.is_whitespace() && !seconds.is_null() && !seconds.is_empty());
|
||||
metadata_for_next_file.track_length_in_seconds = seconds.to_uint();
|
||||
auto display_name = ext_inf.value().substring_view(seconds.length() + 1);
|
||||
VERIFY(!display_name.is_empty() && !display_name.is_null() && !display_name.is_empty());
|
||||
metadata_for_next_file.track_display_title = display_name;
|
||||
//TODO: support the alternative, non-standard #EXTINF value of a key=value dictionary
|
||||
continue;
|
||||
}
|
||||
if (auto playlist = tag("#PLAYLIST:"); playlist.has_value())
|
||||
m_parsed_playlist_title = move(playlist.value());
|
||||
else if (auto ext_grp = tag("#EXTGRP:"); ext_grp.has_value())
|
||||
metadata_for_next_file.group_name = move(ext_grp.value());
|
||||
else if (auto ext_alb = tag("#EXTALB:"); ext_alb.has_value())
|
||||
metadata_for_next_file.album_title = move(ext_alb.value());
|
||||
else if (auto ext_art = tag("#EXTART:"); ext_art.has_value())
|
||||
metadata_for_next_file.album_artist = move(ext_art.value());
|
||||
else if (auto ext_genre = tag("#EXTGENRE:"); ext_genre.has_value())
|
||||
metadata_for_next_file.album_genre = move(ext_genre.value());
|
||||
//TODO: Support M3A files (M3U files with embedded mp3 files)
|
||||
}
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue