diff --git a/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj b/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj
index 09215ad58..c718375b2 100644
--- a/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj
+++ b/aegisub/build/aegisub_vs2008/aegisub_vs2008.vcproj
@@ -1731,6 +1731,14 @@
RelativePath="..\..\src\audio_karaoke.h"
>
+
+
+
+
diff --git a/aegisub/build/msbuild/Aegisub/Aegisub.vcxproj b/aegisub/build/msbuild/Aegisub/Aegisub.vcxproj
index 3605cbff0..0d71961da 100644
--- a/aegisub/build/msbuild/Aegisub/Aegisub.vcxproj
+++ b/aegisub/build/msbuild/Aegisub/Aegisub.vcxproj
@@ -67,6 +67,7 @@
+
@@ -240,6 +241,7 @@
+
diff --git a/aegisub/build/msbuild/Aegisub/Aegisub.vcxproj.filters b/aegisub/build/msbuild/Aegisub/Aegisub.vcxproj.filters
index 316a3b72c..f0022c21b 100644
--- a/aegisub/build/msbuild/Aegisub/Aegisub.vcxproj.filters
+++ b/aegisub/build/msbuild/Aegisub/Aegisub.vcxproj.filters
@@ -207,6 +207,9 @@
Audio\UI
+
+ Audio\UI
+
Audio\UI
@@ -713,6 +716,9 @@
Audio\UI
+
+ Audio\UI
+
Audio\UI
diff --git a/aegisub/src/Makefile b/aegisub/src/Makefile
index e1e1b92f9..414640ce0 100644
--- a/aegisub/src/Makefile
+++ b/aegisub/src/Makefile
@@ -132,6 +132,7 @@ SRC += \
audio_colorscheme.cpp \
audio_display.cpp \
audio_karaoke.cpp \
+ audio_marker_provider_keyframes.cpp \
audio_player.cpp \
audio_provider.cpp \
audio_provider_convert.cpp \
diff --git a/aegisub/src/audio_controller.cpp b/aegisub/src/audio_controller.cpp
index a2fd020c2..aee4e3bca 100644
--- a/aegisub/src/audio_controller.cpp
+++ b/aegisub/src/audio_controller.cpp
@@ -47,6 +47,7 @@
#include "ass_file.h"
#include "audio_controller.h"
+#include "audio_marker_provider_keyframes.h"
#include "audio_provider_dummy.h"
#include "audio_timing.h"
#include "compat.h"
@@ -59,83 +60,6 @@
#include "standard_paths.h"
#include "video_context.h"
-class AudioMarkerKeyframe : public AudioMarker {
- Pen *style;
- int64_t position;
-public:
- AudioMarkerKeyframe(Pen *style, int64_t position) : style(style), position(position) { }
- int64_t GetPosition() const { return position; }
- FeetStyle GetFeet() const { return Feet_None; }
- bool CanSnap() const { return true; }
- wxPen GetStyle() const { return *style; }
- operator int64_t() const { return position; }
-};
-
-class AudioMarkerProviderKeyframes : public AudioMarkerProvider {
- VideoContext *vc;
-
- agi::signal::Connection keyframe_slot;
- agi::signal::Connection audio_open_slot;
- agi::signal::Connection timecode_slot;
- agi::signal::Connection enabled_slot;
-
- std::vector keyframe_samples;
- AudioController *controller;
-
- Pen style;
-
- void Update()
- {
- std::vector const& keyframes = vc->GetKeyFrames();
- agi::vfr::Framerate const& timecodes = vc->FPS();
-
- if (keyframes.empty() || !timecodes.IsLoaded() || !OPT_GET("Audio/Display/Draw/Keyframes")->GetBool())
- {
- if (!keyframe_samples.empty())
- {
- keyframe_samples.clear();
- AnnounceMarkerMoved();
- }
- return;
- }
-
- keyframe_samples.clear();
- keyframe_samples.reserve(keyframes.size());
- for (size_t i = 0; i < keyframes.size(); ++i)
- {
- keyframe_samples.push_back(AudioMarkerKeyframe(&style,
- controller->SamplesFromMilliseconds(timecodes.TimeAtFrame(keyframes[i]))));
- }
- AnnounceMarkerMoved();
- }
-
-public:
- AudioMarkerProviderKeyframes(AudioController *controller, agi::Context *c)
- : vc(c->videoController)
- , keyframe_slot(vc->AddKeyframesListener(&AudioMarkerProviderKeyframes::Update, this))
- , audio_open_slot(controller->AddAudioOpenListener(&AudioMarkerProviderKeyframes::Update, this))
- , timecode_slot(vc->AddTimecodesListener(&AudioMarkerProviderKeyframes::Update, this))
- , enabled_slot(OPT_SUB("Audio/Display/Draw/Keyframes", &AudioMarkerProviderKeyframes::Update, this))
- , controller(controller)
- , style("Colour/Audio Display/Keyframe")
- {
- Update();
- }
-
- void GetMarkers(const SampleRange &range, AudioMarkerVector &out) const
- {
- // Find first and last keyframes inside the range
- std::vector::const_iterator a = std::lower_bound(
- keyframe_samples.begin(), keyframe_samples.end(), range.begin());
- std::vector::const_iterator b = std::upper_bound(
- keyframe_samples.begin(), keyframe_samples.end(), range.end());
-
- // Place pointers to the markers in the output vector
- for (; a != b; ++a)
- out.push_back(&*a);
- }
-};
-
class VideoPositionMarker : public AudioMarker {
Pen style;
int64_t position;
@@ -374,7 +298,7 @@ void AudioController::OpenAudio(const wxString &url)
{
// This is lazy-loaded as the video controller may not exist yet when
// the audio controller is created
- keyframes_marker_provider.reset(new AudioMarkerProviderKeyframes(this, context));
+ keyframes_marker_provider.reset(new AudioMarkerProviderKeyframes(context));
keyframes_marker_provider->AddMarkerMovedListener(std::tr1::bind(std::tr1::ref(AnnounceMarkerMoved)));
}
diff --git a/aegisub/src/audio_marker_provider_keyframes.cpp b/aegisub/src/audio_marker_provider_keyframes.cpp
new file mode 100644
index 000000000..3fa84eff7
--- /dev/null
+++ b/aegisub/src/audio_marker_provider_keyframes.cpp
@@ -0,0 +1,94 @@
+// Copyright (c) 2011, Thomas Goyne
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+// Aegisub Project http://www.aegisub.org/
+//
+// $Id$
+
+/// @file audio_marker_provider_keyframes.cpp
+/// @see audio_marker_provider_keyframes.h
+/// @ingroup audio_ui
+///
+
+#include "config.h"
+
+#include "audio_marker_provider_keyframes.h"
+
+#include "include/aegisub/context.h"
+#include "main.h"
+#include "pen.h"
+#include "video_context.h"
+
+#ifndef AGI_PRE
+#include
+#endif
+
+class AudioMarkerKeyframe : public AudioMarker {
+ Pen *style;
+ int64_t position;
+public:
+ AudioMarkerKeyframe(Pen *style, int64_t position) : style(style), position(position) { }
+ int64_t GetPosition() const { return position; }
+ FeetStyle GetFeet() const { return Feet_None; }
+ bool CanSnap() const { return true; }
+ wxPen GetStyle() const { return *style; }
+ operator int64_t() const { return position; }
+};
+
+AudioMarkerProviderKeyframes::AudioMarkerProviderKeyframes(agi::Context *c)
+: controller(c->audioController)
+, vc(c->videoController)
+, keyframe_slot(vc->AddKeyframesListener(&AudioMarkerProviderKeyframes::Update, this))
+, audio_open_slot(controller->AddAudioOpenListener(&AudioMarkerProviderKeyframes::Update, this))
+, timecode_slot(vc->AddTimecodesListener(&AudioMarkerProviderKeyframes::Update, this))
+, enabled_slot(OPT_SUB("Audio/Display/Draw/Keyframes", &AudioMarkerProviderKeyframes::Update, this))
+, enabled_opt(OPT_GET("Audio/Display/Draw/Keyframes"))
+, style(new Pen("Colour/Audio Display/Keyframe"))
+{
+ Update();
+}
+
+AudioMarkerProviderKeyframes::~AudioMarkerProviderKeyframes() { }
+
+void AudioMarkerProviderKeyframes::Update() {
+ std::vector const& keyframes = vc->GetKeyFrames();
+ agi::vfr::Framerate const& timecodes = vc->FPS();
+
+ if (keyframes.empty() || !timecodes.IsLoaded() || !enabled_opt->GetBool()) {
+ if (!markers.empty()) {
+ markers.clear();
+ AnnounceMarkerMoved();
+ }
+ return;
+ }
+
+ markers.clear();
+ markers.reserve(keyframes.size());
+ for (size_t i = 0; i < keyframes.size(); ++i) {
+ markers.push_back(AudioMarkerKeyframe(style.get(),
+ controller->SamplesFromMilliseconds(timecodes.TimeAtFrame(keyframes[i]))));
+ }
+ AnnounceMarkerMoved();
+}
+
+void AudioMarkerProviderKeyframes::GetMarkers(SampleRange const& range, AudioMarkerVector &out) const {
+ // Find first and last keyframes inside the range
+ std::vector::const_iterator
+ a = lower_bound(markers.begin(), markers.end(), range.begin()),
+ b = upper_bound(markers.begin(), markers.end(), range.end());
+
+ // Place pointers to the markers in the output vector
+ for (; a != b; ++a)
+ out.push_back(&*a);
+}
diff --git a/aegisub/src/audio_marker_provider_keyframes.h b/aegisub/src/audio_marker_provider_keyframes.h
new file mode 100644
index 000000000..6c164accd
--- /dev/null
+++ b/aegisub/src/audio_marker_provider_keyframes.h
@@ -0,0 +1,74 @@
+// Copyright (c) 2011, Thomas Goyne
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+// Aegisub Project http://www.aegisub.org/
+//
+// $Id$
+
+/// @file audio_marker_provider_keyframes.h
+/// @see audio_marker_provider_keyframes.cpp
+/// @ingroup audio_ui
+///
+
+#include "audio_controller.h"
+
+#include
+#include
+
+#ifndef AGI_PRE
+#include
+#endif
+
+class AudioMarkerKeyframe;
+class Pen;
+class VideoContext;
+namespace agi {
+ class OptionValue;
+ struct Context;
+}
+
+/// Marker provider for video keyframes
+class AudioMarkerProviderKeyframes : public AudioMarkerProvider {
+ /// Audio controller for time -> sample conversions
+ AudioController *controller;
+ /// Video controller to get keyframes from
+ VideoContext *vc;
+
+ agi::signal::Connection keyframe_slot;
+ agi::signal::Connection audio_open_slot;
+ agi::signal::Connection timecode_slot;
+ agi::signal::Connection enabled_slot;
+ const agi::OptionValue *enabled_opt;
+
+ /// Current set of markers for the keyframes
+ std::vector markers;
+
+ /// Pen used for all keyframe markers, stored here for performance reasons
+ agi::scoped_ptr style;
+
+ /// Regenerate the list of markers
+ void Update();
+
+public:
+ /// Constructor
+ /// @param c Project context; must have audio and video controllers initialized
+ AudioMarkerProviderKeyframes(agi::Context *c);
+ /// Explicit destructor needed due to members with incomplete types
+ ~AudioMarkerProviderKeyframes();
+
+ /// Get all keyframe markers within a range
+ /// @param range Range of samples to get markers for
+ /// @param[out] out Vector to fill with markers in the range
+ void GetMarkers(SampleRange const& range, AudioMarkerVector &out) const;
+};