mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 09:04:59 +00:00
FileManager: Add "Audio" tab to File Properties window
This commit is contained in:
parent
0a9fa85e86
commit
91b677c81e
4 changed files with 293 additions and 1 deletions
|
@ -7,6 +7,7 @@ serenity_component(
|
|||
|
||||
compile_gml(FileManagerWindow.gml FileManagerWindowGML.h file_manager_window_gml)
|
||||
compile_gml(FileOperationProgress.gml FileOperationProgressGML.h file_operation_progress_gml)
|
||||
compile_gml(PropertiesWindowAudioTab.gml PropertiesWindowAudioTabGML.h properties_window_audio_tab_gml)
|
||||
compile_gml(PropertiesWindowGeneralTab.gml PropertiesWindowGeneralTabGML.h properties_window_general_tab_gml)
|
||||
|
||||
set(SOURCES
|
||||
|
@ -21,8 +22,9 @@ set(SOURCES
|
|||
set(GENERATED_SOURCES
|
||||
FileManagerWindowGML.h
|
||||
FileOperationProgressGML.h
|
||||
PropertiesWindowAudioTabGML.h
|
||||
PropertiesWindowGeneralTabGML.h
|
||||
)
|
||||
|
||||
serenity_app(FileManager ICON app-file-manager)
|
||||
target_link_libraries(FileManager PRIVATE LibCore LibFileSystem LibGfx LibGUI LibDesktop LibConfig LibMain LibThreading)
|
||||
target_link_libraries(FileManager PRIVATE LibAudio LibCore LibFileSystem LibGfx LibGUI LibDesktop LibConfig LibMain LibThreading)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2022-2023, the SerenityOS developers.
|
||||
* Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -9,7 +10,9 @@
|
|||
#include <AK/LexicalPath.h>
|
||||
#include <AK/NumberFormat.h>
|
||||
#include <Applications/FileManager/DirectoryView.h>
|
||||
#include <Applications/FileManager/PropertiesWindowAudioTabGML.h>
|
||||
#include <Applications/FileManager/PropertiesWindowGeneralTabGML.h>
|
||||
#include <LibAudio/Loader.h>
|
||||
#include <LibCore/Directory.h>
|
||||
#include <LibCore/System.h>
|
||||
#include <LibDesktop/Launcher.h>
|
||||
|
@ -58,6 +61,7 @@ ErrorOr<void> PropertiesWindow::create_widgets(bool disable_rename)
|
|||
|
||||
auto tab_widget = TRY(main_widget->try_add<GUI::TabWidget>());
|
||||
TRY(create_general_tab(tab_widget, disable_rename));
|
||||
TRY(create_file_type_specific_tabs(tab_widget));
|
||||
|
||||
auto button_widget = TRY(main_widget->try_add<GUI::Widget>());
|
||||
TRY(button_widget->try_set_layout<GUI::HorizontalBoxLayout>(GUI::Margins {}, 5));
|
||||
|
@ -196,6 +200,62 @@ ErrorOr<void> PropertiesWindow::create_general_tab(GUI::TabWidget& tab_widget, b
|
|||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> PropertiesWindow::create_file_type_specific_tabs(GUI::TabWidget& tab_widget)
|
||||
{
|
||||
auto mapped_file_or_error = Core::MappedFile::map(m_path);
|
||||
if (mapped_file_or_error.is_error()) {
|
||||
warnln("{}: {}", m_path, mapped_file_or_error.release_error());
|
||||
return {};
|
||||
}
|
||||
auto mapped_file = mapped_file_or_error.release_value();
|
||||
|
||||
auto file_name_guess = Core::guess_mime_type_based_on_filename(m_path);
|
||||
auto mime_type = Core::guess_mime_type_based_on_sniffed_bytes(mapped_file->bytes()).value_or(file_name_guess);
|
||||
|
||||
if (mime_type.starts_with("audio/"sv))
|
||||
return create_audio_tab(tab_widget, move(mapped_file));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> PropertiesWindow::create_audio_tab(GUI::TabWidget& tab_widget, NonnullRefPtr<Core::MappedFile> mapped_file)
|
||||
{
|
||||
auto loader_or_error = Audio::Loader::create(mapped_file->bytes());
|
||||
if (loader_or_error.is_error()) {
|
||||
warnln("Failed to open '{}': {}", m_path, loader_or_error.release_error());
|
||||
return {};
|
||||
}
|
||||
auto loader = loader_or_error.release_value();
|
||||
|
||||
auto tab = TRY(tab_widget.try_add_tab<GUI::Widget>("Audio"_short_string));
|
||||
TRY(tab->load_from_gml(properties_window_audio_tab_gml));
|
||||
|
||||
tab->find_descendant_of_type_named<GUI::Label>("audio_type")->set_text(TRY(String::from_deprecated_string(loader->format_name())));
|
||||
auto duration_seconds = loader->total_samples() / loader->sample_rate();
|
||||
tab->find_descendant_of_type_named<GUI::Label>("audio_duration")->set_text(TRY(String::from_deprecated_string(human_readable_digital_time(duration_seconds))));
|
||||
tab->find_descendant_of_type_named<GUI::Label>("audio_sample_rate")->set_text(TRY(String::formatted("{} Hz", loader->sample_rate())));
|
||||
tab->find_descendant_of_type_named<GUI::Label>("audio_format")->set_text(TRY(String::formatted("{}-bit", loader->bits_per_sample())));
|
||||
|
||||
auto channel_count = loader->num_channels();
|
||||
String channels_string;
|
||||
if (channel_count == 1 || channel_count == 2) {
|
||||
channels_string = TRY(String::formatted("{} ({})", channel_count, channel_count == 1 ? "Mono"sv : "Stereo"sv));
|
||||
} else {
|
||||
channels_string = TRY(String::number(channel_count));
|
||||
}
|
||||
tab->find_descendant_of_type_named<GUI::Label>("audio_channels")->set_text(channels_string);
|
||||
|
||||
tab->find_descendant_of_type_named<GUI::Label>("audio_title")->set_text(loader->metadata().title.value_or({}));
|
||||
tab->find_descendant_of_type_named<GUI::Label>("audio_artists")->set_text(TRY(loader->metadata().all_artists()).value_or({}));
|
||||
tab->find_descendant_of_type_named<GUI::Label>("audio_album")->set_text(loader->metadata().album.value_or({}));
|
||||
tab->find_descendant_of_type_named<GUI::Label>("audio_track_number")
|
||||
->set_text(TRY(loader->metadata().track_number.map([](auto number) { return String::number(number); })).value_or({}));
|
||||
tab->find_descendant_of_type_named<GUI::Label>("audio_genre")->set_text(loader->metadata().genre.value_or({}));
|
||||
tab->find_descendant_of_type_named<GUI::Label>("audio_comment")->set_text(loader->metadata().comment.value_or({}));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void PropertiesWindow::update()
|
||||
{
|
||||
m_icon->set_bitmap(GUI::FileIconProvider::icon_for_path(make_full_path(m_name), m_mode).bitmap_for_size(32));
|
||||
|
|
|
@ -29,6 +29,8 @@ private:
|
|||
PropertiesWindow(DeprecatedString const& path, Window* parent = nullptr);
|
||||
ErrorOr<void> create_widgets(bool disable_rename);
|
||||
ErrorOr<void> create_general_tab(GUI::TabWidget&, bool disable_rename);
|
||||
ErrorOr<void> create_file_type_specific_tabs(GUI::TabWidget&);
|
||||
ErrorOr<void> create_audio_tab(GUI::TabWidget&, NonnullRefPtr<Core::MappedFile>);
|
||||
|
||||
struct PermissionMasks {
|
||||
mode_t read;
|
||||
|
|
228
Userland/Applications/FileManager/PropertiesWindowAudioTab.gml
Normal file
228
Userland/Applications/FileManager/PropertiesWindowAudioTab.gml
Normal file
|
@ -0,0 +1,228 @@
|
|||
@GUI::Widget {
|
||||
layout: @GUI::VerticalBoxLayout {
|
||||
margins: [8]
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::GroupBox {
|
||||
title: "Audio"
|
||||
preferred_height: "shrink"
|
||||
layout: @GUI::VerticalBoxLayout {
|
||||
margins: [12, 8, 0]
|
||||
spacing: 2
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Type:"
|
||||
text_alignment: "TopLeft"
|
||||
fixed_width: 80
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
name: "audio_type"
|
||||
text: "MP3"
|
||||
text_alignment: "TopLeft"
|
||||
}
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Duration:"
|
||||
text_alignment: "TopLeft"
|
||||
fixed_width: 80
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
name: "audio_duration"
|
||||
text: "3:21"
|
||||
text_alignment: "TopLeft"
|
||||
}
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Sample rate:"
|
||||
text_alignment: "TopLeft"
|
||||
fixed_width: 80
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
name: "audio_sample_rate"
|
||||
text: "44100 Hz"
|
||||
text_alignment: "TopLeft"
|
||||
}
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Format:"
|
||||
text_alignment: "TopLeft"
|
||||
fixed_width: 80
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
name: "audio_format"
|
||||
text: "16-bit"
|
||||
text_alignment: "TopLeft"
|
||||
}
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Channels:"
|
||||
text_alignment: "TopLeft"
|
||||
fixed_width: 80
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
name: "audio_channels"
|
||||
text: "2 (Stereo)"
|
||||
text_alignment: "TopLeft"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@GUI::GroupBox {
|
||||
title: "Track"
|
||||
layout: @GUI::VerticalBoxLayout {
|
||||
margins: [12, 8, 0]
|
||||
spacing: 2
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
preferred_height: "shrink"
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Title:"
|
||||
text_alignment: "TopLeft"
|
||||
fixed_width: 80
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
name: "audio_title"
|
||||
text: "Ana Ng"
|
||||
text_alignment: "TopLeft"
|
||||
}
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
preferred_height: "shrink"
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Artist(s):"
|
||||
text_alignment: "TopLeft"
|
||||
fixed_width: 80
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
name: "audio_artists"
|
||||
text: "They Might Be Giants"
|
||||
text_alignment: "TopLeft"
|
||||
}
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
preferred_height: "shrink"
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Album:"
|
||||
text_alignment: "TopLeft"
|
||||
fixed_width: 80
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
name: "audio_album"
|
||||
text: "Lincoln"
|
||||
text_alignment: "TopLeft"
|
||||
}
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
preferred_height: "shrink"
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Track number:"
|
||||
text_alignment: "TopLeft"
|
||||
fixed_width: 80
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
name: "audio_track_number"
|
||||
text: "1"
|
||||
text_alignment: "TopLeft"
|
||||
}
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
preferred_height: "shrink"
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Genre:"
|
||||
text_alignment: "TopLeft"
|
||||
fixed_width: 80
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
name: "audio_genre"
|
||||
text: "Alternative"
|
||||
text_alignment: "TopLeft"
|
||||
}
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
preferred_height: "grow"
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Comment:"
|
||||
text_alignment: "TopLeft"
|
||||
fixed_width: 80
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
preferred_height: "grow"
|
||||
name: "audio_comment"
|
||||
text: "Ana Ng and I are getting old and we still haven't walked in the glow of each other's majestic presence."
|
||||
text_alignment: "TopLeft"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue