style: unify identifier naming per updated conventions

Automated with clang-tidy readability-identifier-naming (config added to
.clang-tidy) plus scripted passes, per the updated rules now documented
in CONTRIBUTING.md:

- types (class/struct/enum/alias/template params): PascalCase
- functions, variables, members: snake_case (incl. rational -> Rational)
- private/protected members: trailing underscore; static member
  variables likewise (instance_, available_themes_)
- constants and enum values: snake_case (kLinear -> k_linear,
  F32P -> f32p); ALL_CAPS reserved for macros
- macros: OAK_ prefix (OLIVE_ADD_TEST/OLIVE_ASSERT/OLIVE_CONFIG ->
  OAK_ADD_TEST/OAK_ASSERT/OAK_CONFIG, GL_PREAMBLE -> OAK_GL_PREAMBLE,
  include guards -> OAK_*)
- file names: all lowercase (Current/Plugin/OliveHost/OliveClip/
  OlivePluginInstance -> current/plugin/olivehost/oliveclip/
  oliveplugininstance)
- getters share the member name sans underscore, setters set_foo()
- Qt and third-party (OpenFX) virtual overrides and framework callbacks
  keep their original names (exempt in .clang-tidy)

Manual follow-ups required where automation could not reach:
- string-based QMetaObject/SIGNAL/SLOT references updated to renamed
  methods (AddTask, CreatedFile, DeleteSpecificFile, moveSelectionUp, ...)
- macro bodies referencing renamed methods (OLIVE_CONFIG,
  NODE_DEFAULT_DESTRUCTOR, MANAGEDDISPLAYWIDGET_*)
- self-shadowing locals renamed where signals/methods became same-named
  (size_changed, worker_count, selected_items, import param, filters)
- third_party OFX member/namespace usages restored (OFX::Host::*,
  _created, _clipPrefsDirty, createInstance, clearPersistentMessage)
- STL protocol aliases restored (const_iterator) with .clang-tidy
  ignore rules; qHash overloads restored

Full build and test suite pass: ctest 4/4, ~1960 gtest cases green.
This commit is contained in:
2026-07-19 16:10:54 +08:00
parent cb1718a103
commit bb40b4923e
1014 changed files with 44257 additions and 44220 deletions
+225 -225
View File
@@ -34,13 +34,13 @@ class AudioManagerTest : public ::testing::Test {
protected:
void SetUp() override
{
olive::AudioManager::CreateInstance();
olive::AudioManager::create_instance();
ASSERT_NE(olive::AudioManager::instance(), nullptr);
}
void TearDown() override
{
olive::AudioManager::DestroyInstance();
olive::AudioManager::destroy_instance();
EXPECT_EQ(olive::AudioManager::instance(), nullptr);
}
};
@@ -49,14 +49,14 @@ TEST_F(AudioManagerTest, InstanceLifecycle)
{
// The fixture already created the instance; creating again must be a no-op
olive::AudioManager *first = olive::AudioManager::instance();
olive::AudioManager::CreateInstance();
olive::AudioManager::create_instance();
EXPECT_EQ(olive::AudioManager::instance(), first);
// The stored indices are either paNoDevice or a valid device index with
// channels in the appropriate direction
const PaDeviceIndex output =
olive::AudioManager::instance()->GetOutputDevice();
const PaDeviceIndex input = olive::AudioManager::instance()->GetInputDevice();
olive::AudioManager::instance()->get_output_device();
const PaDeviceIndex input = olive::AudioManager::instance()->get_input_device();
if (Pa_GetDeviceCount() == 0) {
// No devices exist, so nothing could have been selected
@@ -78,67 +78,67 @@ TEST_F(AudioManagerTest, InstanceLifecycle)
TEST_F(AudioManagerTest, SetAndGetNoDevice)
{
olive::AudioManager::instance()->SetOutputDevice(paNoDevice);
EXPECT_EQ(olive::AudioManager::instance()->GetOutputDevice(), paNoDevice);
olive::AudioManager::instance()->set_output_device(paNoDevice);
EXPECT_EQ(olive::AudioManager::instance()->get_output_device(), paNoDevice);
olive::AudioManager::instance()->SetInputDevice(paNoDevice);
EXPECT_EQ(olive::AudioManager::instance()->GetInputDevice(), paNoDevice);
olive::AudioManager::instance()->set_input_device(paNoDevice);
EXPECT_EQ(olive::AudioManager::instance()->get_input_device(), paNoDevice);
}
TEST_F(AudioManagerTest, PushToOutputWithoutDeviceFails)
{
olive::AudioManager::instance()->SetOutputDevice(paNoDevice);
olive::AudioManager::instance()->set_output_device(paNoDevice);
const olive::core::AudioParams params(
48000, olive::core::kChannelLayoutStereo,
olive::core::SampleFormat::F32P);
48000, olive::core::k_channel_layout_stereo,
olive::core::SampleFormat::f32_p);
const QByteArray samples(1024, 0);
QString error;
EXPECT_FALSE(
olive::AudioManager::instance()->PushToOutput(params, samples, &error));
olive::AudioManager::instance()->push_to_output(params, samples, &error));
EXPECT_EQ(error, QStringLiteral("No output device is set"));
// A null error pointer must be tolerated too
EXPECT_FALSE(
olive::AudioManager::instance()->PushToOutput(params, samples, nullptr));
olive::AudioManager::instance()->push_to_output(params, samples, nullptr));
}
TEST_F(AudioManagerTest, StartRecordingWithoutInputDeviceFails)
{
olive::AudioManager::instance()->SetInputDevice(paNoDevice);
olive::AudioManager::instance()->set_input_device(paNoDevice);
// Fails before any encoder or PortAudio stream is created
QString error;
EXPECT_FALSE(
olive::AudioManager::instance()->StartRecording(olive::EncodingParams(),
olive::AudioManager::instance()->start_recording(olive::EncodingParams(),
&error));
// Tearing down a recording that never started must be harmless
olive::AudioManager::instance()->StopRecording();
olive::AudioManager::instance()->stop_recording();
}
TEST_F(AudioManagerTest, OutputControlsWithoutStreamAreNoOps)
{
olive::AudioManager::instance()->SetOutputDevice(paNoDevice);
olive::AudioManager::instance()->set_output_device(paNoDevice);
// No output stream is open; all of these must be harmless no-ops
olive::AudioManager::instance()->StopOutput();
olive::AudioManager::instance()->ClearBufferedOutput();
olive::AudioManager::instance()->SetOutputNotifyInterval(64);
olive::AudioManager::instance()->SetOutputNotifyInterval(0);
olive::AudioManager::instance()->stop_output();
olive::AudioManager::instance()->clear_buffered_output();
olive::AudioManager::instance()->set_output_notify_interval(64);
olive::AudioManager::instance()->set_output_notify_interval(0);
// ...and they must not disturb the device bookkeeping
EXPECT_EQ(olive::AudioManager::instance()->GetOutputDevice(), paNoDevice);
EXPECT_EQ(olive::AudioManager::instance()->get_output_device(), paNoDevice);
}
TEST_F(AudioManagerTest, HardResetKeepsManagerUsable)
{
olive::AudioManager::instance()->HardReset();
olive::AudioManager::instance()->hard_reset();
// Device bookkeeping must survive a PortAudio terminate/init cycle
olive::AudioManager::instance()->SetOutputDevice(paNoDevice);
EXPECT_EQ(olive::AudioManager::instance()->GetOutputDevice(), paNoDevice);
olive::AudioManager::instance()->set_output_device(paNoDevice);
EXPECT_EQ(olive::AudioManager::instance()->get_output_device(), paNoDevice);
}
TEST_F(AudioManagerTest, FindDeviceByNameFallsBackForUnknownName)
@@ -147,9 +147,9 @@ TEST_F(AudioManagerTest, FindDeviceByNameFallsBackForUnknownName)
// devices exist there is nothing to fall back to and the result must be
// exactly paNoDevice; otherwise the fallback is a preferred/default
// device, i.e. a valid index or paNoDevice.
const PaDeviceIndex bogus_output = olive::AudioManager::FindDeviceByName(
const PaDeviceIndex bogus_output = olive::AudioManager::find_device_by_name(
QStringLiteral("OakNoSuchAudioDevice12345"), true);
const PaDeviceIndex bogus_input = olive::AudioManager::FindDeviceByName(
const PaDeviceIndex bogus_input = olive::AudioManager::find_device_by_name(
QStringLiteral("OakNoSuchAudioDevice12345"), false);
if (Pa_GetDeviceCount() == 0) {
@@ -194,7 +194,7 @@ TEST_F(AudioManagerTest, FindDeviceByNameFindsExactMatch)
}
#endif
EXPECT_EQ(olive::AudioManager::FindDeviceByName(
EXPECT_EQ(olive::AudioManager::find_device_by_name(
QString::fromLatin1(info->name), true),
i);
return;
@@ -208,18 +208,18 @@ TEST_F(AudioManagerTest, FindConfigDeviceByNameMatchesConfiguredLookup)
// The config-driven lookup must be exactly FindDeviceByName applied to the
// configured name, and must never return a garbage index
const PaDeviceIndex output =
olive::AudioManager::FindConfigDeviceByName(true);
olive::AudioManager::find_config_device_by_name(true);
const PaDeviceIndex input =
olive::AudioManager::FindConfigDeviceByName(false);
olive::AudioManager::find_config_device_by_name(false);
EXPECT_EQ(output,
olive::AudioManager::FindDeviceByName(
olive::Config::Current()[QStringLiteral("AudioOutput")]
olive::AudioManager::find_device_by_name(
olive::Config::current()[QStringLiteral("AudioOutput")]
.toString(),
true));
EXPECT_EQ(input,
olive::AudioManager::FindDeviceByName(
olive::Config::Current()[QStringLiteral("AudioInput")]
olive::AudioManager::find_device_by_name(
olive::Config::current()[QStringLiteral("AudioInput")]
.toString(),
false));
@@ -236,10 +236,10 @@ TEST_F(AudioManagerTest, PortAudioParamsReflectAudioParams)
}
const olive::core::AudioParams params(
48000, olive::core::kChannelLayoutStereo,
olive::core::SampleFormat::F32);
48000, olive::core::k_channel_layout_stereo,
olive::core::SampleFormat::f32);
const PaStreamParameters p =
olive::AudioManager::GetPortAudioParams(params, 0);
olive::AudioManager::get_port_audio_params(params, 0);
EXPECT_EQ(p.channelCount, 2);
EXPECT_EQ(p.device, 0);
@@ -256,32 +256,32 @@ TEST_F(AudioManagerTest, PortAudioParamsMapsSampleFormats)
const auto format_for = [](olive::core::SampleFormat f) {
const olive::core::AudioParams params(
48000, olive::core::kChannelLayoutMono, f);
return olive::AudioManager::GetPortAudioParams(params, 0).sampleFormat;
48000, olive::core::k_channel_layout_mono, f);
return olive::AudioManager::get_port_audio_params(params, 0).sampleFormat;
};
// Packed and planar variants of the same depth map to the same flag
EXPECT_EQ(format_for(olive::core::SampleFormat::U8),
EXPECT_EQ(format_for(olive::core::SampleFormat::u8),
PaSampleFormat(paUInt8));
EXPECT_EQ(format_for(olive::core::SampleFormat::U8P),
EXPECT_EQ(format_for(olive::core::SampleFormat::u8_p),
PaSampleFormat(paUInt8));
EXPECT_EQ(format_for(olive::core::SampleFormat::S16),
EXPECT_EQ(format_for(olive::core::SampleFormat::s16),
PaSampleFormat(paInt16));
EXPECT_EQ(format_for(olive::core::SampleFormat::S16P),
EXPECT_EQ(format_for(olive::core::SampleFormat::s16_p),
PaSampleFormat(paInt16));
EXPECT_EQ(format_for(olive::core::SampleFormat::S32),
EXPECT_EQ(format_for(olive::core::SampleFormat::s32),
PaSampleFormat(paInt32));
EXPECT_EQ(format_for(olive::core::SampleFormat::S32P),
EXPECT_EQ(format_for(olive::core::SampleFormat::s32_p),
PaSampleFormat(paInt32));
EXPECT_EQ(format_for(olive::core::SampleFormat::F32),
EXPECT_EQ(format_for(olive::core::SampleFormat::f32),
PaSampleFormat(paFloat32));
EXPECT_EQ(format_for(olive::core::SampleFormat::F32P),
EXPECT_EQ(format_for(olive::core::SampleFormat::f32_p),
PaSampleFormat(paFloat32));
// 64-bit depths have no PortAudio equivalent and map to paCustomFormat(0)
EXPECT_EQ(format_for(olive::core::SampleFormat::S64), PaSampleFormat(0));
EXPECT_EQ(format_for(olive::core::SampleFormat::F64), PaSampleFormat(0));
EXPECT_EQ(format_for(olive::core::SampleFormat::INVALID),
EXPECT_EQ(format_for(olive::core::SampleFormat::s64), PaSampleFormat(0));
EXPECT_EQ(format_for(olive::core::SampleFormat::f64), PaSampleFormat(0));
EXPECT_EQ(format_for(olive::core::SampleFormat::invalid),
PaSampleFormat(0));
}
@@ -294,24 +294,24 @@ TEST_F(AudioManagerTest, PortAudioParamsMapsSampleFormats)
class TestViewerOutput : public olive::ViewerOutput {
public:
using olive::ViewerOutput::ViewerOutput;
using olive::ViewerOutput::AddStream;
using olive::ViewerOutput::SetStream;
using olive::ViewerOutput::add_stream;
using olive::ViewerOutput::set_stream;
};
class ViewerOutputTest : public ::testing::Test {
protected:
void SetUp() override
{
olive::ColorManager::SetUpDefaultConfig();
olive::ColorManager::set_up_default_config();
project_ = std::make_unique<olive::Project>();
project_->Initialize();
project_->initialize();
viewer_ = new TestViewerOutput();
viewer_->setParent(project_.get());
}
template <typename T> T *AddNode()
template <typename T> T *add_node()
{
T *node = new T();
node->setParent(project_.get());
@@ -324,82 +324,82 @@ protected:
TEST_F(ViewerOutputTest, DefaultConstruction)
{
EXPECT_EQ(viewer_->Name(), QStringLiteral("Viewer"));
EXPECT_EQ(viewer_->name(), QStringLiteral("Viewer"));
EXPECT_EQ(viewer_->id(),
QStringLiteral("org.olivevideoeditor.Olive.vieweroutput"));
EXPECT_TRUE(viewer_->Category().contains(olive::Node::kCategoryOutput));
EXPECT_TRUE(viewer_->category().contains(olive::Node::k_category_output));
// One default video and audio stream, no subtitle streams
EXPECT_EQ(viewer_->GetVideoStreamCount(), 1);
EXPECT_EQ(viewer_->GetAudioStreamCount(), 1);
EXPECT_EQ(viewer_->GetSubtitleStreamCount(), 0);
EXPECT_EQ(viewer_->GetTotalStreamCount(), 2);
EXPECT_EQ(viewer_->get_video_stream_count(), 1);
EXPECT_EQ(viewer_->get_audio_stream_count(), 1);
EXPECT_EQ(viewer_->get_subtitle_stream_count(), 0);
EXPECT_EQ(viewer_->get_total_stream_count(), 2);
EXPECT_NE(viewer_->GetWorkArea(), nullptr);
EXPECT_NE(viewer_->GetMarkers(), nullptr);
EXPECT_NE(viewer_->get_work_area(), nullptr);
EXPECT_NE(viewer_->get_markers(), nullptr);
EXPECT_EQ(viewer_->GetPlayhead(), olive::rational(0));
EXPECT_EQ(viewer_->GetLength(), olive::rational(0));
EXPECT_EQ(viewer_->GetVideoLength(), olive::rational(0));
EXPECT_EQ(viewer_->GetAudioLength(), olive::rational(0));
EXPECT_EQ(viewer_->get_playhead(), olive::Rational(0));
EXPECT_EQ(viewer_->get_length(), olive::Rational(0));
EXPECT_EQ(viewer_->get_video_length(), olive::Rational(0));
EXPECT_EQ(viewer_->get_audio_length(), olive::Rational(0));
EXPECT_EQ(viewer_->GetConnectedTextureOutput(), nullptr);
EXPECT_EQ(viewer_->GetConnectedSampleOutput(), nullptr);
EXPECT_EQ(viewer_->GetConnectedWaveform(), nullptr);
EXPECT_EQ(viewer_->get_connected_texture_output(), nullptr);
EXPECT_EQ(viewer_->get_connected_sample_output(), nullptr);
EXPECT_EQ(viewer_->get_connected_waveform(), nullptr);
// The autocache API is currently a stub that always reports disabled
EXPECT_FALSE(viewer_->IsVideoAutoCacheEnabled());
EXPECT_FALSE(viewer_->is_video_auto_cache_enabled());
}
TEST_F(ViewerOutputTest, SetAndGetVideoParams)
{
const olive::VideoParams vp(1920, 1080, olive::rational(1, 30),
olive::PixelFormat::U8, 4);
viewer_->SetVideoParams(vp);
const olive::VideoParams vp(1920, 1080, olive::Rational(1, 30),
olive::PixelFormat::u8, 4);
viewer_->set_video_params(vp);
EXPECT_EQ(viewer_->GetVideoParams(), vp);
EXPECT_EQ(viewer_->GetVideoParams().width(), 1920);
EXPECT_EQ(viewer_->GetVideoParams().height(), 1080);
EXPECT_EQ(viewer_->get_video_params(), vp);
EXPECT_EQ(viewer_->get_video_params().width(), 1920);
EXPECT_EQ(viewer_->get_video_params().height(), 1080);
// Out-of-range indices return invalid params instead of garbage
EXPECT_FALSE(viewer_->GetVideoParams(5).is_valid());
EXPECT_FALSE(viewer_->get_video_params(5).is_valid());
}
TEST_F(ViewerOutputTest, SetAndGetAudioParams)
{
const olive::core::AudioParams ap(48000, olive::core::kChannelLayoutStereo,
olive::core::SampleFormat::F32P);
viewer_->SetAudioParams(ap);
const olive::core::AudioParams ap(48000, olive::core::k_channel_layout_stereo,
olive::core::SampleFormat::f32_p);
viewer_->set_audio_params(ap);
EXPECT_EQ(viewer_->GetAudioParams(), ap);
EXPECT_EQ(viewer_->get_audio_params(), ap);
// The default-constructed stream uses the viewer's default sample format
const olive::core::SampleFormat default_format =
olive::ViewerOutput::kDefaultSampleFormat;
EXPECT_EQ(viewer_->GetAudioParams().format(), default_format);
olive::ViewerOutput::k_default_sample_format;
EXPECT_EQ(viewer_->get_audio_params().format(), default_format);
// Out-of-range indices return invalid params instead of garbage
EXPECT_FALSE(viewer_->GetAudioParams(9).is_valid());
EXPECT_FALSE(viewer_->get_audio_params(9).is_valid());
}
TEST_F(ViewerOutputTest, SetAndGetSubtitleParams)
{
olive::SubtitleParams subs;
subs.push_back(olive::Subtitle(
olive::TimeRange(olive::rational(0), olive::rational(2)),
olive::TimeRange(olive::Rational(0), olive::Rational(2)),
QStringLiteral("hello")));
EXPECT_EQ(viewer_->AddStream(olive::Track::kSubtitle,
EXPECT_EQ(viewer_->add_stream(olive::Track::k_subtitle,
QVariant::fromValue(subs)),
0);
EXPECT_EQ(viewer_->GetSubtitleStreamCount(), 1);
EXPECT_EQ(viewer_->get_subtitle_stream_count(), 1);
ASSERT_TRUE(viewer_->GetSubtitleParams(0).is_valid());
EXPECT_EQ(viewer_->GetSubtitleParams(0).duration(), olive::rational(2));
EXPECT_TRUE(viewer_->HasEnabledSubtitleStreams());
ASSERT_TRUE(viewer_->get_subtitle_params(0).is_valid());
EXPECT_EQ(viewer_->get_subtitle_params(0).duration(), olive::Rational(2));
EXPECT_TRUE(viewer_->has_enabled_subtitle_streams());
// Out-of-range indices return invalid (empty) params
EXPECT_FALSE(viewer_->GetSubtitleParams(3).is_valid());
EXPECT_FALSE(viewer_->get_subtitle_params(3).is_valid());
}
TEST_F(ViewerOutputTest, VideoParamSignals)
@@ -409,41 +409,41 @@ TEST_F(ViewerOutputTest, VideoParamSignals)
int pixel_aspect_emissions = 0;
int interlacing_emissions = 0;
int params_emissions = 0;
olive::rational emitted_frame_rate;
QObject::connect(viewer_, &olive::ViewerOutput::SizeChanged,
olive::Rational emitted_frame_rate;
QObject::connect(viewer_, &olive::ViewerOutput::size_changed,
[&size_emissions](int, int) { ++size_emissions; });
QObject::connect(viewer_, &olive::ViewerOutput::FrameRateChanged,
QObject::connect(viewer_, &olive::ViewerOutput::frame_rate_changed,
[&frame_rate_emissions, &emitted_frame_rate](
const olive::rational &r) {
const olive::Rational &r) {
++frame_rate_emissions;
emitted_frame_rate = r;
});
QObject::connect(viewer_, &olive::ViewerOutput::PixelAspectChanged,
[&pixel_aspect_emissions](const olive::rational &) {
QObject::connect(viewer_, &olive::ViewerOutput::pixel_aspect_changed,
[&pixel_aspect_emissions](const olive::Rational &) {
++pixel_aspect_emissions;
});
QObject::connect(viewer_, &olive::ViewerOutput::InterlacingChanged,
QObject::connect(viewer_, &olive::ViewerOutput::interlacing_changed,
[&interlacing_emissions](olive::VideoParams::Interlacing) {
++interlacing_emissions;
});
QObject::connect(viewer_, &olive::ViewerOutput::VideoParamsChanged,
QObject::connect(viewer_, &olive::ViewerOutput::video_params_changed,
[&params_emissions]() { ++params_emissions; });
// Every aspect differs from the cached defaults, so all signals fire once
const olive::VideoParams vp(1280, 720, olive::rational(1, 60),
olive::PixelFormat::U8, 4, olive::rational(2),
olive::VideoParams::kInterlacedTopFirst);
viewer_->SetVideoParams(vp);
const olive::VideoParams vp(1280, 720, olive::Rational(1, 60),
olive::PixelFormat::u8, 4, olive::Rational(2),
olive::VideoParams::k_interlaced_top_first);
viewer_->set_video_params(vp);
EXPECT_EQ(size_emissions, 1);
EXPECT_EQ(frame_rate_emissions, 1);
EXPECT_EQ(emitted_frame_rate, olive::rational(60, 1));
EXPECT_EQ(emitted_frame_rate, olive::Rational(60, 1));
EXPECT_EQ(pixel_aspect_emissions, 1);
EXPECT_EQ(interlacing_emissions, 1);
EXPECT_EQ(params_emissions, 1);
// Setting identical params only re-emits the unconditional change signal
viewer_->SetVideoParams(vp);
viewer_->set_video_params(vp);
EXPECT_EQ(size_emissions, 1);
EXPECT_EQ(frame_rate_emissions, 1);
@@ -457,24 +457,24 @@ TEST_F(ViewerOutputTest, AudioParamSignals)
int sample_rate_emissions = 0;
int params_emissions = 0;
int emitted_sample_rate = 0;
QObject::connect(viewer_, &olive::ViewerOutput::SampleRateChanged,
QObject::connect(viewer_, &olive::ViewerOutput::sample_rate_changed,
[&sample_rate_emissions, &emitted_sample_rate](int sr) {
++sample_rate_emissions;
emitted_sample_rate = sr;
});
QObject::connect(viewer_, &olive::ViewerOutput::AudioParamsChanged,
QObject::connect(viewer_, &olive::ViewerOutput::audio_params_changed,
[&params_emissions]() { ++params_emissions; });
const olive::core::AudioParams ap(44100, olive::core::kChannelLayoutStereo,
olive::core::SampleFormat::F32P);
viewer_->SetAudioParams(ap);
const olive::core::AudioParams ap(44100, olive::core::k_channel_layout_stereo,
olive::core::SampleFormat::f32_p);
viewer_->set_audio_params(ap);
EXPECT_EQ(sample_rate_emissions, 1);
EXPECT_EQ(emitted_sample_rate, 44100);
EXPECT_EQ(params_emissions, 1);
// Same sample rate again: no SampleRateChanged, but AudioParamsChanged
viewer_->SetAudioParams(ap);
viewer_->set_audio_params(ap);
EXPECT_EQ(sample_rate_emissions, 1);
EXPECT_EQ(params_emissions, 2);
@@ -483,214 +483,214 @@ TEST_F(ViewerOutputTest, AudioParamSignals)
TEST_F(ViewerOutputTest, SetPlayheadEmitsPlayheadChanged)
{
int emissions = 0;
olive::rational emitted;
QObject::connect(viewer_, &olive::ViewerOutput::PlayheadChanged,
[&emissions, &emitted](const olive::rational &t) {
olive::Rational emitted;
QObject::connect(viewer_, &olive::ViewerOutput::playhead_changed,
[&emissions, &emitted](const olive::Rational &t) {
++emissions;
emitted = t;
});
viewer_->SetPlayhead(olive::rational(3, 2));
viewer_->set_playhead(olive::Rational(3, 2));
EXPECT_EQ(emissions, 1);
EXPECT_EQ(emitted, olive::rational(3, 2));
EXPECT_EQ(viewer_->GetPlayhead(), olive::rational(3, 2));
EXPECT_EQ(emitted, olive::Rational(3, 2));
EXPECT_EQ(viewer_->get_playhead(), olive::Rational(3, 2));
}
TEST_F(ViewerOutputTest, VerifyLengthWithoutConnectionsStaysZero)
{
int length_emissions = 0;
QObject::connect(viewer_, &olive::ViewerOutput::LengthChanged,
[&length_emissions](const olive::rational &) {
QObject::connect(viewer_, &olive::ViewerOutput::length_changed,
[&length_emissions](const olive::Rational &) {
++length_emissions;
});
viewer_->VerifyLength();
viewer_->VerifyLength();
viewer_->verify_length();
viewer_->verify_length();
// Nothing is connected, so all lengths stay zero and nothing is emitted
EXPECT_EQ(viewer_->GetLength(), olive::rational(0));
EXPECT_EQ(viewer_->GetVideoLength(), olive::rational(0));
EXPECT_EQ(viewer_->GetAudioLength(), olive::rational(0));
EXPECT_EQ(viewer_->get_length(), olive::Rational(0));
EXPECT_EQ(viewer_->get_video_length(), olive::Rational(0));
EXPECT_EQ(viewer_->get_audio_length(), olive::Rational(0));
EXPECT_EQ(length_emissions, 0);
EXPECT_EQ(viewer_->GetVideoCacheRange(),
olive::TimeRange(olive::rational(0), olive::rational(0)));
EXPECT_EQ(viewer_->GetAudioCacheRange(),
olive::TimeRange(olive::rational(0), olive::rational(0)));
EXPECT_EQ(viewer_->get_video_cache_range(),
olive::TimeRange(olive::Rational(0), olive::Rational(0)));
EXPECT_EQ(viewer_->get_audio_cache_range(),
olive::TimeRange(olive::Rational(0), olive::Rational(0)));
}
TEST_F(ViewerOutputTest, StreamEnableDisable)
{
ASSERT_TRUE(viewer_->HasEnabledVideoStreams());
ASSERT_TRUE(viewer_->HasEnabledAudioStreams());
ASSERT_TRUE(viewer_->has_enabled_video_streams());
ASSERT_TRUE(viewer_->has_enabled_audio_streams());
olive::VideoParams vp = viewer_->GetVideoParams();
olive::VideoParams vp = viewer_->get_video_params();
vp.set_enabled(false);
viewer_->SetVideoParams(vp);
viewer_->set_video_params(vp);
EXPECT_FALSE(viewer_->HasEnabledVideoStreams());
EXPECT_FALSE(viewer_->GetFirstEnabledVideoStream().is_valid());
EXPECT_TRUE(viewer_->GetEnabledVideoStreams().isEmpty());
EXPECT_FALSE(viewer_->has_enabled_video_streams());
EXPECT_FALSE(viewer_->get_first_enabled_video_stream().is_valid());
EXPECT_TRUE(viewer_->get_enabled_video_streams().isEmpty());
olive::core::AudioParams ap = viewer_->GetAudioParams();
olive::core::AudioParams ap = viewer_->get_audio_params();
ap.set_enabled(false);
viewer_->SetAudioParams(ap);
viewer_->set_audio_params(ap);
EXPECT_FALSE(viewer_->HasEnabledAudioStreams());
EXPECT_FALSE(viewer_->GetFirstEnabledAudioStream().is_valid());
EXPECT_TRUE(viewer_->GetEnabledAudioStreams().isEmpty());
EXPECT_TRUE(viewer_->GetEnabledStreamsAsReferences().isEmpty());
EXPECT_FALSE(viewer_->has_enabled_audio_streams());
EXPECT_FALSE(viewer_->get_first_enabled_audio_stream().is_valid());
EXPECT_TRUE(viewer_->get_enabled_audio_streams().isEmpty());
EXPECT_TRUE(viewer_->get_enabled_streams_as_references().isEmpty());
}
TEST_F(ViewerOutputTest, AddAndSetStreams)
{
const olive::VideoParams vp2(640, 360, olive::rational(1, 25),
olive::PixelFormat::U8, 4);
const olive::VideoParams vp2(640, 360, olive::Rational(1, 25),
olive::PixelFormat::u8, 4);
EXPECT_EQ(viewer_->AddStream(olive::Track::kVideo,
EXPECT_EQ(viewer_->add_stream(olive::Track::k_video,
QVariant::fromValue(vp2)),
1);
EXPECT_EQ(viewer_->GetVideoStreamCount(), 2);
EXPECT_EQ(viewer_->GetVideoParams(1), vp2);
EXPECT_EQ(viewer_->GetTotalStreamCount(), 3);
EXPECT_EQ(viewer_->get_video_stream_count(), 2);
EXPECT_EQ(viewer_->get_video_params(1), vp2);
EXPECT_EQ(viewer_->get_total_stream_count(), 3);
// References enumerate the enabled streams in video/audio/subtitle order
const QVector<olive::Track::Reference> refs =
viewer_->GetEnabledStreamsAsReferences();
viewer_->get_enabled_streams_as_references();
ASSERT_EQ(refs.size(), 3);
EXPECT_EQ(refs.at(0), olive::Track::Reference(olive::Track::kVideo, 0));
EXPECT_EQ(refs.at(1), olive::Track::Reference(olive::Track::kVideo, 1));
EXPECT_EQ(refs.at(2), olive::Track::Reference(olive::Track::kAudio, 0));
EXPECT_EQ(refs.at(0), olive::Track::Reference(olive::Track::k_video, 0));
EXPECT_EQ(refs.at(1), olive::Track::Reference(olive::Track::k_video, 1));
EXPECT_EQ(refs.at(2), olive::Track::Reference(olive::Track::k_audio, 0));
// SetStream replaces an existing element in place
const olive::core::AudioParams ap2(
32000, olive::core::kChannelLayoutMono, olive::core::SampleFormat::S16);
EXPECT_EQ(viewer_->SetStream(olive::Track::kAudio,
32000, olive::core::k_channel_layout_mono, olive::core::SampleFormat::s16);
EXPECT_EQ(viewer_->set_stream(olive::Track::k_audio,
QVariant::fromValue(ap2), 0),
0);
EXPECT_EQ(viewer_->GetAudioStreamCount(), 1);
EXPECT_EQ(viewer_->GetAudioParams(0), ap2);
EXPECT_EQ(viewer_->get_audio_stream_count(), 1);
EXPECT_EQ(viewer_->get_audio_params(0), ap2);
// kNone is not a valid stream type
EXPECT_EQ(viewer_->AddStream(olive::Track::kNone, QVariant()), -1);
EXPECT_EQ(viewer_->add_stream(olive::Track::k_none, QVariant()), -1);
}
TEST_F(ViewerOutputTest, ConnectTextureEmitsAndResolves)
{
auto *solid = AddNode<olive::SolidGenerator>();
auto *solid = add_node<olive::SolidGenerator>();
int emissions = 0;
QObject::connect(viewer_, &olive::ViewerOutput::TextureInputChanged,
QObject::connect(viewer_, &olive::ViewerOutput::texture_input_changed,
[&emissions]() { ++emissions; });
olive::Node::ConnectEdge(
solid, olive::NodeInput(viewer_, olive::ViewerOutput::kTextureInput));
olive::Node::connect_edge(
solid, olive::NodeInput(viewer_, olive::ViewerOutput::k_texture_input));
EXPECT_EQ(emissions, 1);
EXPECT_EQ(viewer_->GetConnectedTextureOutput(), solid);
EXPECT_EQ(viewer_->get_connected_texture_output(), solid);
// Explicit value hints set on the input are reported through the getter
const olive::Node::ValueHint hint({ olive::NodeValue::kTexture }, 2,
const olive::Node::ValueHint hint({ olive::NodeValue::k_texture }, 2,
QStringLiteral("tex"));
viewer_->SetValueHintForInput(olive::ViewerOutput::kTextureInput, hint);
viewer_->set_value_hint_for_input(olive::ViewerOutput::k_texture_input, hint);
const olive::Node::ValueHint got =
viewer_->GetConnectedTextureValueHint();
viewer_->get_connected_texture_value_hint();
ASSERT_EQ(got.types().size(), 1);
EXPECT_EQ(got.types().first(), olive::NodeValue::kTexture);
EXPECT_EQ(got.types().first(), olive::NodeValue::k_texture);
EXPECT_EQ(got.index(), 2);
EXPECT_EQ(got.tag(), QStringLiteral("tex"));
olive::Node::DisconnectEdge(
solid, olive::NodeInput(viewer_, olive::ViewerOutput::kTextureInput));
olive::Node::disconnect_edge(
solid, olive::NodeInput(viewer_, olive::ViewerOutput::k_texture_input));
EXPECT_EQ(emissions, 2);
EXPECT_EQ(viewer_->GetConnectedTextureOutput(), nullptr);
EXPECT_EQ(viewer_->get_connected_texture_output(), nullptr);
}
TEST_F(ViewerOutputTest, ConnectSamplesResolves)
{
auto *clip = AddNode<olive::ClipBlock>();
auto *clip = add_node<olive::ClipBlock>();
olive::Node::ConnectEdge(
clip, olive::NodeInput(viewer_, olive::ViewerOutput::kSamplesInput));
olive::Node::connect_edge(
clip, olive::NodeInput(viewer_, olive::ViewerOutput::k_samples_input));
EXPECT_EQ(viewer_->GetConnectedSampleOutput(), clip);
EXPECT_EQ(viewer_->GetConnectedWaveform(), clip->waveform_cache());
EXPECT_EQ(viewer_->get_connected_sample_output(), clip);
EXPECT_EQ(viewer_->get_connected_waveform(), clip->waveform_cache());
// Without an explicit hint the sample value hint is empty
EXPECT_TRUE(viewer_->GetConnectedSampleValueHint().types().isEmpty());
EXPECT_TRUE(viewer_->get_connected_sample_value_hint().types().isEmpty());
olive::Node::DisconnectEdge(
clip, olive::NodeInput(viewer_, olive::ViewerOutput::kSamplesInput));
olive::Node::disconnect_edge(
clip, olive::NodeInput(viewer_, olive::ViewerOutput::k_samples_input));
EXPECT_EQ(viewer_->GetConnectedSampleOutput(), nullptr);
EXPECT_EQ(viewer_->GetConnectedWaveform(), nullptr);
EXPECT_EQ(viewer_->get_connected_sample_output(), nullptr);
EXPECT_EQ(viewer_->get_connected_waveform(), nullptr);
}
TEST_F(ViewerOutputTest, InvalidateCacheWithoutConnectionsIsSafe)
{
// With nothing connected the request path is skipped entirely; this must
// neither crash nor produce a length change
viewer_->InvalidateCache(olive::TimeRange(olive::rational(0),
olive::rational(1)),
olive::ViewerOutput::kTextureInput, -1,
viewer_->invalidate_cache(olive::TimeRange(olive::Rational(0),
olive::Rational(1)),
olive::ViewerOutput::k_texture_input, -1,
olive::Node::InvalidateCacheOptions());
viewer_->InvalidateCache(olive::TimeRange(olive::rational(0),
olive::rational(1)),
olive::ViewerOutput::kSamplesInput, -1,
viewer_->invalidate_cache(olive::TimeRange(olive::Rational(0),
olive::Rational(1)),
olive::ViewerOutput::k_samples_input, -1,
olive::Node::InvalidateCacheOptions());
EXPECT_EQ(viewer_->GetLength(), olive::rational(0));
EXPECT_EQ(viewer_->get_length(), olive::Rational(0));
}
TEST_F(ViewerOutputTest, ValueRepushTagsStreams)
{
olive::NodeValueRow row;
row.insert(olive::ViewerOutput::kTextureInput,
olive::NodeValue(olive::NodeValue::kTexture, 0));
row.insert(olive::ViewerOutput::kSamplesInput,
olive::NodeValue(olive::NodeValue::kSamples, 0));
row.insert(olive::ViewerOutput::k_texture_input,
olive::NodeValue(olive::NodeValue::k_texture, 0));
row.insert(olive::ViewerOutput::k_samples_input,
olive::NodeValue(olive::NodeValue::k_samples, 0));
olive::NodeValueTable table;
viewer_->Value(row, olive::NodeGlobals(), &table);
viewer_->value(row, olive::NodeGlobals(), &table);
// The texture value is re-pushed tagged as video stream 0
const QString video_tag =
olive::Track::Reference(olive::Track::kVideo, 0).ToString();
EXPECT_EQ(table.Get(olive::NodeValue::kTexture, video_tag).type(),
olive::NodeValue::kTexture);
olive::Track::Reference(olive::Track::k_video, 0).to_string();
EXPECT_EQ(table.get(olive::NodeValue::k_texture, video_tag).type(),
olive::NodeValue::k_texture);
// The samples value is re-pushed tagged as audio stream 0
const QString audio_tag =
olive::Track::Reference(olive::Track::kAudio, 0).ToString();
EXPECT_EQ(table.Get(olive::NodeValue::kSamples, audio_tag).type(),
olive::NodeValue::kSamples);
EXPECT_EQ(table.Get(olive::NodeValue::kSamples).tag(), audio_tag);
olive::Track::Reference(olive::Track::k_audio, 0).to_string();
EXPECT_EQ(table.get(olive::NodeValue::k_samples, audio_tag).type(),
olive::NodeValue::k_samples);
EXPECT_EQ(table.get(olive::NodeValue::k_samples).tag(), audio_tag);
}
TEST_F(ViewerOutputTest, LastUsedEncodingParamsRoundTrip)
{
olive::EncodingParams params;
params.SetFilename(QStringLiteral("/tmp/oak-export.mp4"));
params.set_filename(QStringLiteral("/tmp/oak-export.mp4"));
viewer_->SetLastUsedEncodingParams(params);
viewer_->set_last_used_encoding_params(params);
EXPECT_EQ(viewer_->GetLastUsedEncodingParams().filename(),
EXPECT_EQ(viewer_->get_last_used_encoding_params().filename(),
QStringLiteral("/tmp/oak-export.mp4"));
}
TEST_F(ViewerOutputTest, SaveLoadCustomRoundTrip)
{
viewer_->GetWorkArea()->set_enabled(true);
viewer_->GetWorkArea()->set_range(
olive::TimeRange(olive::rational(1), olive::rational(5)));
viewer_->get_work_area()->set_enabled(true);
viewer_->get_work_area()->set_range(
olive::TimeRange(olive::Rational(1), olive::Rational(5)));
QString xml;
QXmlStreamWriter writer(&xml);
writer.writeStartDocument();
writer.writeStartElement(QStringLiteral("custom"));
viewer_->SaveCustom(&writer);
viewer_->save_custom(&writer);
writer.writeEndElement();
writer.writeEndDocument();
@@ -702,56 +702,56 @@ TEST_F(ViewerOutputTest, SaveLoadCustomRoundTrip)
ASSERT_EQ(reader.name(), QStringLiteral("custom"));
olive::ViewerOutput loaded;
ASSERT_TRUE(loaded.LoadCustom(&reader, nullptr));
EXPECT_TRUE(loaded.GetWorkArea()->enabled());
EXPECT_EQ(loaded.GetWorkArea()->range(), viewer_->GetWorkArea()->range());
ASSERT_TRUE(loaded.load_custom(&reader, nullptr));
EXPECT_TRUE(loaded.get_work_area()->enabled());
EXPECT_EQ(loaded.get_work_area()->range(), viewer_->get_work_area()->range());
}
TEST_F(ViewerOutputTest, RetranslateSetsInputNames)
{
viewer_->Retranslate();
viewer_->retranslate();
EXPECT_EQ(viewer_->GetInputName(olive::ViewerOutput::kVideoParamsInput),
EXPECT_EQ(viewer_->get_input_name(olive::ViewerOutput::k_video_params_input),
QStringLiteral("Video Parameters"));
EXPECT_EQ(viewer_->GetInputName(olive::ViewerOutput::kAudioParamsInput),
EXPECT_EQ(viewer_->get_input_name(olive::ViewerOutput::k_audio_params_input),
QStringLiteral("Audio Parameters"));
EXPECT_EQ(viewer_->GetInputName(olive::ViewerOutput::kSubtitleParamsInput),
EXPECT_EQ(viewer_->get_input_name(olive::ViewerOutput::k_subtitle_params_input),
QStringLiteral("Subtitle Parameters"));
EXPECT_EQ(viewer_->GetInputName(olive::ViewerOutput::kTextureInput),
EXPECT_EQ(viewer_->get_input_name(olive::ViewerOutput::k_texture_input),
QStringLiteral("Texture"));
EXPECT_EQ(viewer_->GetInputName(olive::ViewerOutput::kSamplesInput),
EXPECT_EQ(viewer_->get_input_name(olive::ViewerOutput::k_samples_input),
QStringLiteral("Samples"));
}
TEST_F(ViewerOutputTest, AutoCacheStubsAlwaysReportDisabled)
{
EXPECT_FALSE(viewer_->IsVideoAutoCacheEnabled());
EXPECT_FALSE(viewer_->is_video_auto_cache_enabled());
// The setter is a stub and must not change the reported state
viewer_->SetVideoAutoCacheEnabled(true);
EXPECT_FALSE(viewer_->IsVideoAutoCacheEnabled());
viewer_->set_video_auto_cache_enabled(true);
EXPECT_FALSE(viewer_->is_video_auto_cache_enabled());
}
TEST_F(ViewerOutputTest, SetWaveformEnabledWithoutConnectionIsSafe)
{
// No samples input connected: enabling waveform requests must not crash
viewer_->SetWaveformEnabled(true);
EXPECT_EQ(viewer_->GetConnectedWaveform(), nullptr);
viewer_->set_waveform_enabled(true);
EXPECT_EQ(viewer_->get_connected_waveform(), nullptr);
viewer_->SetWaveformEnabled(false);
viewer_->set_waveform_enabled(false);
}
TEST_F(ViewerOutputTest, FrequencyRateDataReflectsEnabledStreams)
{
// A video stream takes priority and is reported as a frame rate
QString rate = viewer_->data(olive::Node::FREQUENCY_RATE).toString();
QString rate = viewer_->data(olive::Node::frequency_rate).toString();
EXPECT_TRUE(rate.endsWith(QStringLiteral(" FPS")));
// With the video stream disabled, the audio sample rate is reported
olive::VideoParams vp = viewer_->GetVideoParams();
olive::VideoParams vp = viewer_->get_video_params();
vp.set_enabled(false);
viewer_->SetVideoParams(vp);
viewer_->set_video_params(vp);
rate = viewer_->data(olive::Node::FREQUENCY_RATE).toString();
rate = viewer_->data(olive::Node::frequency_rate).toString();
EXPECT_TRUE(rate.endsWith(QStringLiteral(" Hz")));
}