Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions src/audio_provider_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
#include <libaegisub/path.h>
#include <libaegisub/string.h>

#include <algorithm>
#include <initializer_list>

using namespace agi;

std::unique_ptr<AudioProvider> CreateAvisynthAudioProvider(fs::path const& filename, BackgroundRunner *);
Expand All @@ -36,16 +39,20 @@ struct factory {
const char *name;
std::unique_ptr<AudioProvider> (*create)(fs::path const&, BackgroundRunner *);
bool hidden;
std::vector<const char *> extensions;
};

const std::initializer_list<factory> providers = {
{"Dummy", CreateDummyAudioProvider, true},
{"PCM", CreatePCMAudioProvider, true},
{"Dummy", CreateDummyAudioProvider, true, {}},
{"PCM", CreatePCMAudioProvider, true, {".w64", ".wav"}},
#ifdef WITH_FFMS2
{"FFmpegSource", CreateFFmpegSourceAudioProvider, false},
{"FFmpegSource", CreateFFmpegSourceAudioProvider, false,
{".aac", ".ac3", ".ape", ".asf", ".avi", ".avs", ".d2v", ".dts", ".eac3", ".flac", ".m2ts",
".m4a", ".m4v", ".mka", ".mkv", ".mov", ".mp3", ".mp4", ".mpeg", ".mpg", ".ogg", ".ogm", ".opus",
".ts", ".w64", ".wav", ".webm", ".wma", ".wmv"}},
#endif
#ifdef WITH_AVISYNTH
{"Avisynth", CreateAvisynthAudioProvider, false},
{"Avisynth", CreateAvisynthAudioProvider, false, {".avi", ".avs"}},
#endif
};
}
Expand All @@ -54,6 +61,15 @@ std::vector<std::string> GetAudioProviderNames() {
return ::GetClasses(providers);
}

std::vector<std::string> GetAudioProviderFileExtensions() {
std::vector<std::string> extensions;
for (auto const& provider : providers)
extensions.insert(extensions.end(), provider.extensions.begin(), provider.extensions.end());
std::sort(extensions.begin(), extensions.end());
extensions.erase(std::unique(extensions.begin(), extensions.end()), extensions.end());
return extensions;
}

std::unique_ptr<agi::AudioProvider> GetAudioProvider(fs::path const& filename,
Path const& path_helper,
BackgroundRunner *br) {
Expand Down
1 change: 1 addition & 0 deletions src/audio_provider_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ std::unique_ptr<agi::AudioProvider> GetAudioProvider(agi::fs::path const& filena
agi::Path const& path_helper,
agi::BackgroundRunner *br);
std::vector<std::string> GetAudioProviderNames();
std::vector<std::string> GetAudioProviderFileExtensions();
8 changes: 5 additions & 3 deletions src/command/audio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
#include "../libresrc/libresrc.h"
#include "../options.h"
#include "../project.h"
#include "../audio_provider_factory.h"
#include "../provider_file_formats.h"
#include "../selection_controller.h"
#include "../utils.h"
#include "../video_controller.h"
Expand Down Expand Up @@ -79,9 +81,9 @@ struct audio_open final : public Command {
STR_HELP("Open an audio file")

void operator()(agi::Context *c) override {
auto str = from_wx(_("Audio Formats") + " (*.aac,*.ac3,*.ape,*.dts,*.eac3,*.flac,*.m4a,*.mka,*.mp3,*.mp4,*.ogg,*.opus,*.w64,*.wav,*.wma)|*.aac;*.ac3;*.ape;*.dts;*.eac3;*.flac;*.m4a;*.mka;*.mp3;*.mp4;*.ogg;*.opus;*.w64;*.wav;*.wma|"
+ _("Video Formats") + " (*.asf,*.avi,*.avs,*.d2v,*.m2ts,*.m4v,*.mkv,*.mov,*.mp4,*.mpeg,*.mpg,*.ogm,*.webm,*.wmv,*.ts)|*.asf;*.avi;*.avs;*.d2v;*.m2ts;*.m4v;*.mkv;*.mov;*.mp4;*.mpeg;*.mpg;*.ogm;*.webm;*.wmv;*.ts|"
+ _("All Files") + " (*.*)|*.*");
auto formats = MakeWildcard(GetAudioProviderFileExtensions());
auto str = from_wx(_("Audio and Video Formats")) + " (" + formats + ")|" + formats + "|"
+ from_wx(_("All Files")) + " (*.*)|*.*";
auto filename = OpenFileSelector(wxGETTEXT_IN_CONTEXT("dialog title", "Open Audio File"), "Path/Last/Audio", "", "", str, c->parent);
if (!filename.empty())
c->project->LoadAudio(filename);
Expand Down
7 changes: 5 additions & 2 deletions src/command/video.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
#include "../libresrc/libresrc.h"
#include "../options.h"
#include "../project.h"
#include "../provider_file_formats.h"
#include "../video_provider_manager.h"
#include "../selection_controller.h"
#include "../utils.h"
#include "../video_controller.h"
Expand Down Expand Up @@ -588,8 +590,9 @@ struct video_open final : public Command {
STR_HELP("Open a video file")

void operator()(agi::Context *c) override {
auto str = from_wx(_("Video Formats") + " (*.asf,*.avi,*.avs,*.d2v,*.h264,*.hevc,*.m2ts,*.m4v,*.mkv,*.mov,*.mp4,*.mpeg,*.mpg,*.ogm,*.webm,*.wmv,*.ts,*.y4m,*.yuv)|*.asf;*.avi;*.avs;*.d2v;*.h264;*.hevc;*.m2ts;*.m4v;*.mkv;*.mov;*.mp4;*.mpeg;*.mpg;*.ogm;*.webm;*.wmv;*.ts;*.y4m;*.yuv|"
+ _("All Files") + " (*.*)|*.*");
auto formats = MakeWildcard(VideoProviderFactory::GetFileExtensions());
auto str = from_wx(_("Video Formats")) + " (" + formats + ")|" + formats + "|"
+ from_wx(_("All Files")) + " (*.*)|*.*";
auto filename = OpenFileSelector(_("Open Video File"), "Path/Last/Video", "", "", str, c->parent);
if (!filename.empty())
c->project->LoadVideo(filename);
Expand Down
1 change: 1 addition & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ aegisub_src = files(
'preferences.cpp',
'preferences_base.cpp',
'project.cpp',
'provider_file_formats.cpp',
'resolution_resampler.cpp',
'search_replace_engine.cpp',
'selection_controller.cpp',
Expand Down
60 changes: 10 additions & 50 deletions src/project.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "audio_provider_factory.h"
#include "base_grid.h"
#include "charset_detect.h"
#include "audio_provider_factory.h"
#include "compat.h"
#include "dialog_progress.h"
#include "dialogs.h"
Expand All @@ -31,11 +32,13 @@
#include "include/aegisub/video_provider.h"
#include "mkv_wrap.h"
#include "options.h"
#include "provider_file_formats.h"
#include "selection_controller.h"
#include "subs_controller.h"
#include "utils.h"
#include "video_controller.h"
#include "video_display.h"
#include "video_provider_manager.h"

#include <libaegisub/audio/provider.h>
#include <libaegisub/format_path.h>
Expand Down Expand Up @@ -431,31 +434,6 @@ void Project::CloseKeyframes() {
void Project::LoadList(std::vector<agi::fs::path> const& files) {
// Keep these lists sorted

// Video formats
const char *videoList[] = {
".asf",
".avi",
".avs",
".d2v",
".h264",
".hevc",
".m2ts",
".m4v",
".mkv",
".mov",
".mp4",
".mpeg",
".mpg",
".ogm",
".rm",
".rmvb",
".ts",
".webm",
".wmv",
".y4m",
".yuv"
};

// Subtitle formats
const char *subsList[] = {
".ass",
Expand All @@ -465,28 +443,10 @@ void Project::LoadList(std::vector<agi::fs::path> const& files) {
".ttxt"
};

// Audio formats
const char *audioList[] = {
".aac",
".ac3",
".ape",
".dts",
".eac3",
".flac",
".m4a",
".mka",
".mp3",
".ogg",
".opus",
".w64",
".wav",
".wma"
};

auto search = [](const char **begin, const char **end, std::string const& str) {
return std::binary_search(begin, end, str.c_str(), [](const char *a, const char *b) {
return strcmp(a, b) < 0;
});
auto video_formats = VideoProviderFactory::GetFileExtensions();
auto audio_formats = GetAudioProviderFileExtensions();
auto search = [](auto const& formats, std::string const& str) {
return std::binary_search(formats.begin(), formats.end(), str);
};

agi::fs::path audio, video, subs, timecodes, keyframes;
Expand Down Expand Up @@ -520,11 +480,11 @@ void Project::LoadList(std::vector<agi::fs::path> const& files) {
continue;
}

if (subs.empty() && search(std::begin(subsList), std::end(subsList), ext))
if (subs.empty() && std::binary_search(std::begin(subsList), std::end(subsList), ext.c_str(), [](const char *a, const char *b) { return strcmp(a, b) < 0; }))
subs = file;
if (video.empty() && search(std::begin(videoList), std::end(videoList), ext))
if (video.empty() && search(video_formats, ext))
video = file;
if (audio.empty() && search(std::begin(audioList), std::end(audioList), ext))
if (audio.empty() && search(audio_formats, ext))
audio = file;
}

Expand Down
14 changes: 14 additions & 0 deletions src/provider_file_formats.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) 2026, Aegisub contributors
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted.

#include "provider_file_formats.h"

std::string MakeWildcard(std::vector<std::string> const& extensions) {
std::string result;
for (auto const& extension : extensions) {
if (!result.empty()) result += ';';
result += '*' + extension;
}
return result;
}
11 changes: 11 additions & 0 deletions src/provider_file_formats.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) 2026, Aegisub contributors
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted.

#pragma once

#include <string>
#include <vector>

/// Turn an extension list into the pattern portion of a wx file-dialog filter.
std::string MakeWildcard(std::vector<std::string> const& extensions);
23 changes: 19 additions & 4 deletions src/video_provider_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@

#include <wx/translation.h>

#include <algorithm>
#include <initializer_list>

std::unique_ptr<VideoProvider> CreateDummyVideoProvider(agi::fs::path const&, agi::ycbcr::Header, agi::BackgroundRunner *);
std::unique_ptr<VideoProvider> CreateYUV4MPEGVideoProvider(agi::fs::path const&, agi::ycbcr::Header, agi::BackgroundRunner *);
std::unique_ptr<VideoProvider> CreateFFmpegSourceVideoProvider(agi::fs::path const&, agi::ycbcr::Header, agi::BackgroundRunner *);
Expand All @@ -39,16 +42,19 @@ namespace {
const char *name;
std::unique_ptr<VideoProvider> (*create)(agi::fs::path const&, agi::ycbcr::Header, agi::BackgroundRunner *);
bool hidden;
std::vector<const char *> extensions;
};

const std::initializer_list<factory> providers = {
{"Dummy", CreateDummyVideoProvider, true},
{"YUV4MPEG", CreateYUV4MPEGVideoProvider, true},
{"Dummy", CreateDummyVideoProvider, true, {}},
{"YUV4MPEG", CreateYUV4MPEGVideoProvider, true, {".y4m", ".yuv"}},
#ifdef WITH_FFMS2
{"FFmpegSource", CreateFFmpegSourceVideoProvider, false},
{"FFmpegSource", CreateFFmpegSourceVideoProvider, false,
{".asf", ".avi", ".avs", ".d2v", ".h264", ".hevc", ".m2ts", ".m4v", ".mkv", ".mov", ".mp4",
".mpeg", ".mpg", ".ogm", ".ts", ".webm", ".wmv"}},
#endif
#ifdef WITH_AVISYNTH
{"Avisynth", CreateAvisynthVideoProvider, false},
{"Avisynth", CreateAvisynthVideoProvider, false, {".avi", ".avs", ".d2v"}},
#endif
};
}
Expand All @@ -57,6 +63,15 @@ std::vector<std::string> VideoProviderFactory::GetClasses() {
return ::GetClasses(providers);
}

std::vector<std::string> VideoProviderFactory::GetFileExtensions() {
std::vector<std::string> extensions;
for (auto const& provider : providers)
extensions.insert(extensions.end(), provider.extensions.begin(), provider.extensions.end());
std::sort(extensions.begin(), extensions.end());
extensions.erase(std::unique(extensions.begin(), extensions.end()), extensions.end());
return extensions;
}

std::unique_ptr<VideoProvider> VideoProviderFactory::GetProvider(agi::fs::path const& filename, agi::ycbcr::Header colormatrix, agi::BackgroundRunner *br) {
auto preferred = OPT_GET("Video/Provider")->GetString();
auto sorted = GetSorted(providers, preferred);
Expand Down
1 change: 1 addition & 0 deletions src/video_provider_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ namespace agi { class BackgroundRunner; }

struct VideoProviderFactory {
static std::vector<std::string> GetClasses();
static std::vector<std::string> GetFileExtensions();
static std::unique_ptr<VideoProvider> GetProvider(agi::fs::path const& video_file, agi::ycbcr::Header colormatrix, agi::BackgroundRunner *br);
};
Loading